學(xué)習(xí)心得:C語言實現(xiàn)鏈表的操作超詳細

今天將給大家講述鏈表的學(xué)習(xí)心得。學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu),毋庸置疑鏈表必須學(xué)好,后面的棧、隊列、樹、圖都是以鏈表為基礎(chǔ)的;鏈表的種類很多,有單鏈表、雙鏈表、循環(huán)鏈表、非循環(huán)鏈表;在此,我們以非循環(huán)單鏈表為例,來講鏈表的創(chuàng)建、求長度、排序、插入和排序。

1.什么是鏈表

鏈表我的理解要包含以下特征:

(1).由n個節(jié)點離散分配;

(2).每個節(jié)點通過指針連接

(3)每一個節(jié)點由一個前驅(qū)節(jié)點和一個后驅(qū)節(jié)點

(4).首節(jié)點沒有前驅(qū)節(jié)點,尾節(jié)點沒有后驅(qū)節(jié)點;

滿足上面的4條,我們就稱為鏈表;鏈表既然由很多個節(jié)點,那節(jié)點又由什么組成?節(jié)點由兩個部分組成,一是數(shù)據(jù)域,用來存放有效數(shù)據(jù);二是指針域,用來指向下一個節(jié)點;下面用C語言來構(gòu)建鏈表數(shù)據(jù)結(jié)構(gòu),首先應(yīng)該構(gòu)造出節(jié)點,然后再把所有的節(jié)點連起來,就構(gòu)成了鏈表;

(1)節(jié)點的構(gòu)造

typedef struct Node

{

int data;//數(shù)據(jù)域,用來存放數(shù)據(jù)域;

struct Node *pNext;//定義一個結(jié)構(gòu)體指針,指向下一次個與當(dāng)前節(jié)點數(shù)據(jù)類型相同的節(jié)點

}NODE,*PNODE; //NODE等價于 struct Node; PNODE等價于struct Node *; 此處用大寫是為了與變量區(qū)分,可以讓人容易變出是個數(shù)據(jù)類型

typedef 只是給數(shù)據(jù)類型取個別名,即 typedef 數(shù)據(jù)類型 別名;我們知道struct Node 是我們定義的數(shù)據(jù)類型;

(2)鏈表的創(chuàng)建

在創(chuàng)建鏈表之前,我們需要需要了解一下專業(yè)術(shù)語:

首節(jié)點:存放第一個有效數(shù)據(jù)的節(jié)點;

尾節(jié)點:存放最后一個有效數(shù)據(jù)的節(jié)點;

頭節(jié)點:頭節(jié)點的數(shù)據(jù)類型與首節(jié)點的數(shù)據(jù)類型相同,并且頭節(jié)點是首節(jié)點前面的那個節(jié)點,并不存放有效數(shù)據(jù);頭節(jié)點的存在只是為了方便鏈表的操作。

頭指針:指向頭節(jié)點的指針;

尾指針:指向尾節(jié)點的指針;

首先,我們應(yīng)該創(chuàng)建一個頭節(jié)點,并用頭指針指向它,用C語言描述:用malloc向計算機申請一塊內(nèi)存,并定義一個指向與頭節(jié)點數(shù)據(jù)類型相同的指針(一定要判斷申請內(nèi)存是否成功);

然后,要知道要創(chuàng)建鏈表的長度,用一個循環(huán)來每次創(chuàng)建一個節(jié)點,并把每個節(jié)點連在一起;

假如我們要在頭節(jié)點phead后面插入節(jié)點p:

(1)把頭節(jié)點的指針域指向P節(jié)點,即pHead->pNext=p;

(2)把p節(jié)點的指針域指向NULL,即p->pNext=NULL;

這樣就可以了嗎? 想想我們就可以發(fā)現(xiàn),當(dāng)我們要插入多個節(jié)點時,頭節(jié)點始終指向最后添加的一個數(shù)據(jù),以前的節(jié)點通過頭指針此時已經(jīng)找不到了;我們定義一個尾指針pTail,始終用來指向鏈表的結(jié)尾,每次只在pTail后面添加節(jié)點。

偽算法:

(1)定義一個尾指針pTail,并初始化,使它指向頭節(jié)點,即pTail=pHead;

(2)在pTail后面添加節(jié)點,修改指針:

pTail->pNext=p;

p->pNext=NULL;

pTail=p; //使pTail指向鏈表最后一個元素

PNODE Create_List(void)

{

int len; //存放鏈表的長度

int i; //循環(huán)變量

int val;//用來臨時存放用戶輸入的結(jié)點的值

PNODE List;

PNODE pHead=(PNODE)malloc(sizeof(NODE));//分配一個頭節(jié)點

if(NULL==pHead)

{

printf("Memory allocation failure");

exit(-1);

}

else

{ PNODE pTail=pHead;

pHead->pNext=NULL;

printf("please input the length of list: "); //需要一個指針始終指向鏈表的結(jié)尾

scanf("%d",&len);

for(i=0;i

{

PNODE p=(PNODE)malloc(sizeof(NODE));

if(NULL==p)

{

printf("Memory allocation failure");

exit(-1);

}

else

{

printf("please input the value of list: ");

scanf("%d",&val);

p->data=val;

pTail->pNext=p;

p->pNext=NULL;

pTail=p;

}

}

}

return pHead;

}


小編給大家推薦一個學(xué)習(xí)氛圍超好的地方,C/C++交流企鵝裙:870963251!適合在校大學(xué)生,小白,想轉(zhuǎn)行,想通過這個找工作的加入。裙里有大量學(xué)習(xí)資料,有大神解答交流問題,每晚都有免費的直播課程


2.向鏈表中插入元素

假如要在節(jié)點2的前面插入節(jié)點p,我們首先要找到節(jié)點2的前驅(qū)節(jié)點1,假設(shè)現(xiàn)在q指針指向節(jié)點1,則

(1)p->pNext=q->pNext;

(2)q->pNext=p;

程序代碼如下:

//鏈表的第pos有效元素前面插入元素val,首先我們應(yīng)該找到第pos個元素前面一個元素的位置;

//當(dāng)鏈表有3個元素時,pos=4,將不會進行插入操作

bool Insert_List(PNODE pHead,int pos,int val)

{

int i=0;

PNODE p=pHead;

while((NULL!=p)&&(i

{

p=p->pNext;

i++;

}

if(p==NULL||i>pos-1) //把鏈表為空的情況考慮進去了;i>pos-1 可以防止用戶輸入錯誤;

return false;

//程序執(zhí)行到這之后,i=pos-1;p指針指向鏈表第pos個有效節(jié)點的前驅(qū),即指向第pos-1節(jié)點;

PNODE q=(PNODE)malloc(sizeof(NODE));

q->data=val;

q->pNext=p->pNext;

p->pNext=q;

}


3.刪除鏈表中的元素

假如要刪除節(jié)點2,只需要把節(jié)點1指針域指針指向節(jié)點3,但不要忘記釋放節(jié)點2所占的內(nèi)存,否則將會造成內(nèi)存泄漏;首先必須找到節(jié)點2的前驅(qū)節(jié)點1,假設(shè)p指向節(jié)點1。

(1)q=p->pNext; //首先用q保存要刪除節(jié)點的地址;

(2)p->pNext=q->pNext; //q->pNext=p->pNext->pNext; 修改指針使節(jié)點1指向節(jié)點3;

(3)free(q); //釋放節(jié)點2所占的內(nèi)存;

bool Delete_List(PNODE pHead,int pos,int *val)

{

int i=0;

PNODE p=pHead;

while((NULL!=p)&&(i

{

p=p->pNext;

i++;

}

if(p==NULL||i>pos-1) //把鏈表為空的情況考慮進去了;i>pos-1 可以防止用戶輸入錯誤;

return false;

//程序執(zhí)行到這之后,i=pos-1;

PNODE q=p->pNext; //q指向待刪除的節(jié)點;

*val=q->data;

p->pNext=q->pNext; //修改鏈表指針指向;

free(q); //釋放q所指向節(jié)點的內(nèi)存;

q=NULL;//千萬不可以忘記,否則會出現(xiàn)野指針;

}


4.鏈表元素的排序

快速排序和冒泡排序的思想對于鏈表這個數(shù)據(jù)結(jié)構(gòu)同樣適用,下面是一個用選擇排序來實現(xiàn)鏈表的排序;

//鏈表有效元素的個數(shù)

int Length_List(PNODE pHead)

{ int len=0; //定義變量要記得初始化;

PNODE p=pHead->pNext;

while(NULL!=p)

{

len++;

p=p->pNext;

}

return len;

}

//對鏈表中的元素進行排序

void Sort_List(PNODE pHead)

{

int i,j;

int temp;

int len=Length_List(pHead);

PNODE p,q;//指向鏈表第一個有效元素

for(i=0,p=pHead->pNext;ipNext)

{

for(j=i+1,q=p->pNext;jpNext)

{

//交換數(shù)據(jù)

if(p->data>q->data)

{

temp=p->data;

p->data=q->data;

q->data=temp;

}

}

}

}

和數(shù)組排序很像,只是這里需要兩個指針p、q不停地移動,來獲取鏈表中的數(shù)據(jù)元素;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容