C++編程語言實(shí)現(xiàn)單鏈表詳情
一、單鏈表簡單介紹
首先,我們再回顧一下線性表的兩種存儲方式——順序存儲與鏈?zhǔn)酱鎯?/p>

上圖左邊為順序存儲,右邊為鏈?zhǔn)酱鎯?br />
之前我們利用數(shù)組來實(shí)現(xiàn)順序表,對于順序表的優(yōu)點(diǎn)缺點(diǎn),總結(jié)來說就是,查找方便,增刪復(fù)雜。
線性表之順序存儲的優(yōu)缺點(diǎn)

而鏈表特點(diǎn)可以說恰恰相反,增刪方便,查找復(fù)雜。
今天實(shí)現(xiàn)的是鏈表中最簡單的一種——單鏈表(每個(gè)結(jié)點(diǎn)中只含有一個(gè)指針域)
對于鏈表我們只知道它每個(gè)結(jié)點(diǎn)的存儲的物理地址是不連續(xù)的,但邏輯上還是符合線性表“一對一”的特點(diǎn)。因此,我們就需要用“線”(指針)把這些不連續(xù)的結(jié)點(diǎn)按順序連接起來。
鏈表的結(jié)點(diǎn)在內(nèi)存中存儲不連續(xù)

通過指針把每個(gè)結(jié)點(diǎn)按順序連起來

到這里我們可以發(fā)現(xiàn),要想表示鏈表中的結(jié)點(diǎn),光存儲結(jié)點(diǎn)的數(shù)據(jù)是不夠的,還得有指針。因此,單鏈表的結(jié)點(diǎn)結(jié)構(gòu)如下:
數(shù)據(jù)域存儲數(shù)據(jù),指針域存儲指針

//================線性表的單鏈表存儲結(jié)構(gòu)=================
typedef struct LNode {
ElemType data;//數(shù)據(jù)域
struct LNode *next;//指針域
}LNode;
注意:因?yàn)橹羔樖侵赶蛎總€(gè)結(jié)點(diǎn)的,也就是指向struct LNode這個(gè)自定義的結(jié)構(gòu)體類型,所以指針的類型就是struct LNode*。
二、下面我們先實(shí)現(xiàn)單鏈表的初始化。
單鏈表的初始化其實(shí)就是創(chuàng)建幾個(gè)結(jié)點(diǎn),然后用指針把他們連接起來。
先創(chuàng)建一個(gè)頭指針,實(shí)際上就是創(chuàng)建一個(gè)頭結(jié)點(diǎn),然后頭指針指向頭結(jié)點(diǎn)就OK

LNode* CreateList_L(int n) {//順位序輸入n個(gè)元素的值,建立帶表頭結(jié)點(diǎn)的單鏈線性表L
LNode *p = (LNode*)malloc(sizeof(LNode));//創(chuàng)建頭結(jié)點(diǎn)(p也就是頭指針)
LNode *temp = p;//聲明一個(gè)指針指向頭結(jié)點(diǎn),用于遍歷鏈表(不是頭指針,因?yàn)樗皇菚簳r(shí)指向頭結(jié)點(diǎn))
//生成鏈表
for (int i = n; i > 0; --i)
{
LNode *node = (LNode *)malloc(sizeof(LNode));//創(chuàng)建結(jié)點(diǎn)
if (node){//分配地址成功
scanf_s("%c", &(node->data));
node->next = NULL;
//建立新結(jié)點(diǎn)與直接前驅(qū)結(jié)點(diǎn)的邏輯關(guān)系
temp->next = node;
temp = temp->next;
}
else {//如果分配地址失敗,則返回錯(cuò)誤信息
printf("結(jié)點(diǎn)創(chuàng)建失?。n");
}
}
return p;
}
三、實(shí)現(xiàn)單鏈表的插入與刪除數(shù)據(jù)
單鏈表插數(shù)據(jù)情況

觀察可知,我們要實(shí)現(xiàn)插入操作,需要的操作是一樣的。
S1:將后繼結(jié)點(diǎn)的指針賦給新結(jié)點(diǎn)的指針域;
S2:將前驅(qū)節(jié)點(diǎn)的指針域改為指向新結(jié)點(diǎn)的指針。
注意:S1和S2不能換順序。
//===============================算法2.9==========================
Status ListInsert_L(LNode *L, int i, ElemType e) {
//在帶頭結(jié)點(diǎn)的單鏈表L中第i個(gè)位置之前插入元素e
int j = 0;
LNode *p = L;
while (p&&j < i - 1) {
p = p->next;
++j;
}//尋找第i-1個(gè)結(jié)點(diǎn)
if (!p || j > i - 1)return ERROR;//i小于1或者大于表長時(shí)
LNode* s = (LNode*)malloc(sizeof(LNode));//生成新的結(jié)點(diǎn)
s->data = e; s->next = p->next;//S1
p->next = s;//S2
return OK;
}
單鏈表刪除數(shù)據(jù)示意圖

觀察可知,只需要將待刪結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)的指針域的值換成待刪結(jié)點(diǎn)的后繼結(jié)點(diǎn)的指針即可。
//=====================算法2.10=================================
Status ListDelete_L(LNode *L, int i, ElemType *e) {
//在帶頭結(jié)點(diǎn)的單鏈表L中,刪除第i個(gè)元素,并由e返回其值
LNode *p = L;
int j = 0;
while (p->next&&j < i - 1) {//尋找第i個(gè)結(jié)點(diǎn),并令p指向其前驅(qū)
p = p->next; ++j;
}
if (!(p->next) || j > i - 1)return ERROR;//刪除位置不合理
LNode *q = p->next; p->next = q->next;//刪除并釋放結(jié)點(diǎn)
*e = q->data; free(q);
return OK;
}
三、參考代碼實(shí)現(xiàn)與截圖
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define ElemType char
typedef int Status;
//================線性表的單鏈表存儲結(jié)構(gòu)==================
typedef struct LNode {
ElemType data;//數(shù)據(jù)域
struct LNode *next;//指針域
}LNode;
LNode* CreateList_L(int n) {//順位序輸入n個(gè)元素的值,建立帶表頭結(jié)點(diǎn)的單鏈線性表L
LNode *p = (LNode*)malloc(sizeof(LNode));//創(chuàng)建頭結(jié)點(diǎn)
LNode *temp = p;//聲明一個(gè)指針指向頭結(jié)點(diǎn),用于遍歷鏈表(不是頭指針)
//生成鏈表
for (int i = n; i > 0; --i)
{
LNode *node = (LNode *)malloc(sizeof(LNode));//創(chuàng)建結(jié)點(diǎn)
if (node){//分配地址成功
scanf_s("%c", &(node->data));
node->next = NULL;
//建立新結(jié)點(diǎn)與直接前驅(qū)結(jié)點(diǎn)的邏輯關(guān)系
temp->next = node;
temp = temp->next;
}
else {//如果分配地址失敗,則返回錯(cuò)誤信息
printf("結(jié)點(diǎn)創(chuàng)建失敗!\n");
}
}
return p;
}
//===============================算法2.9==========================
Status ListInsert_L(LNode *L, int i, ElemType e) {
//在帶頭結(jié)點(diǎn)的單鏈表L中第i個(gè)位置之前插入元素e
int j = 0;
LNode *p = L;
while (p&&j < i - 1) {
p = p->next;
++j;
}//尋找第i-1個(gè)結(jié)點(diǎn)
if (!p || j > i - 1)return ERROR;//i小于1或者大于表長時(shí)
LNode* s = (LNode*)malloc(sizeof(LNode));//生成新的結(jié)點(diǎn)
s->data = e; s->next = p->next;
p->next = s;
return OK;
}
//=====================算法2.10=================================
Status ListDelete_L(LNode *L, int i, ElemType *e) {
//在帶頭結(jié)點(diǎn)的單鏈表L中,刪除第i個(gè)元素,并由e返回其值
LNode *p = L;
int j = 0;
while (p->next&&j < i - 1) {//尋找第i個(gè)結(jié)點(diǎn),并令p指向其前驅(qū)
p = p->next; ++j;
}
if (!(p->next) || j > i - 1)return ERROR;//刪除位置不合理
LNode *q = p->next; p->next = q->next;//刪除并釋放結(jié)點(diǎn)
*e = q->data; free(q);
return OK;
}
void display(LNode *L) {
LNode *temp =L;//將temp指針重新指向頭結(jié)點(diǎn)
//只要temp指針指向的結(jié)點(diǎn)的next不是Null,就執(zhí)行輸出語句。
while (temp->next) {
temp = temp->next;
printf("%c", temp->data);
}
printf("\n");
}
int main() {
LNode *L = NULL;
L=CreateList_L(5);
display(L);
ListInsert_L(L, 2, 'Y');
display(L);
ElemType e;
ListDelete_L(L, 2, &e);
display(L);
printf("返回值為:%c", e);
system("pause");
return 0;
}

初始化鏈表為abcdef,在第2個(gè)位置插入Y,然后刪除Y
到此這篇關(guān)于C++編程語言實(shí)現(xiàn)單鏈表詳情的文章就介紹到這了,更多相關(guān)C++編程語言實(shí)現(xiàn)單鏈表內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
全面了解結(jié)構(gòu)體、聯(lián)合體和枚舉類型
下面小編就為大家?guī)硪黄媪私饨Y(jié)構(gòu)體、聯(lián)合體和枚舉類型。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-07-07
詳解C++中實(shí)現(xiàn)繼承string類的MyString類的步驟
這篇文章主要介紹了C++中實(shí)現(xiàn)繼承string類的MyString類的步驟,其中的要點(diǎn)是要實(shí)現(xiàn)運(yùn)算符的重載,需要的朋友可以參考下2016-04-04
C++中實(shí)現(xiàn)fibonacci數(shù)列的幾種方法
本文主要介紹了C++中實(shí)現(xiàn)fibonacci數(shù)列的幾種方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
VC6.0代碼自動提示 VC6.0在win7環(huán)境下代碼提示智能化
作為程序猿的你,是否已經(jīng)喜歡或習(xí)慣依賴IDE開發(fā)環(huán)境呢,有了IDE環(huán)境,即使你想不起方法全名,只要知道某個(gè)前綴,或哪怕在提示列表中,一一查詢,也可以找到自己想找的方法或?qū)傩?/div> 2013-01-01
C語言實(shí)現(xiàn)將字符串轉(zhuǎn)換成整數(shù)
這篇文章主要為大家詳細(xì)介紹了如何用C語言寫一個(gè)函數(shù),把字符串轉(zhuǎn)換成整數(shù),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
C++設(shè)計(jì)與實(shí)現(xiàn)ORM系統(tǒng)實(shí)例詳解
這篇文章主要為大家介紹了C++設(shè)計(jì)與實(shí)現(xiàn)ORM系統(tǒng)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09最新評論

