溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

c語(yǔ)言線(xiàn)性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是什么

發(fā)布時(shí)間:2021-11-22 16:15:48 來(lái)源:億速云 閱讀:143 作者:iii 欄目:編程語(yǔ)言

這篇文章主要講解了“c語(yǔ)言線(xiàn)性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是什么”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“c語(yǔ)言線(xiàn)性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是什么”吧!

頭指針:鏈表中第一個(gè)節(jié)點(diǎn)的存儲(chǔ)位置叫頭指針。

頭結(jié)點(diǎn)第一個(gè)結(jié)點(diǎn)前放的一個(gè)不存儲(chǔ)任何數(shù)據(jù)的結(jié)點(diǎn)。

頭結(jié)點(diǎn)與頭指針的區(qū)別:

    1、頭指針是指鏈表指向第一個(gè)結(jié)點(diǎn)的指針,若鏈表有頭結(jié)點(diǎn),則是指向頭結(jié)點(diǎn)的指針;

    2、頭指針具有標(biāo)識(shí)作用,所以常用頭指針冠以鏈表的名字;

    3、無(wú)論鏈表是否為空,頭指針均不為空。頭指針是鏈表的必要元素。

    4、頭結(jié)點(diǎn)是為了操作的統(tǒng)一和方便而設(shè)立的,放在第一元素的借點(diǎn)之前,其數(shù)據(jù)域一般無(wú)意義(也可存儲(chǔ)鏈表的長(zhǎng)度);

    5、有了頭結(jié)點(diǎn),對(duì)在第一個(gè)元素節(jié)點(diǎn)點(diǎn)之前插入結(jié)點(diǎn)和刪除第一個(gè)結(jié)點(diǎn),其他操作與其他結(jié)點(diǎn)的操作統(tǒng)一了;

    6、頭結(jié)點(diǎn)不一定是鏈表的必要元素

文字描述還是很抽象,讓我們來(lái)看圖,這樣更直觀:



c語(yǔ)言線(xiàn)性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是什么

理清了這幾個(gè)概念,接下來(lái)我們開(kāi)始用c語(yǔ)言實(shí)現(xiàn)單鏈表的基本操作(這里會(huì)把帶頭結(jié)點(diǎn)與不帶頭結(jié)點(diǎn)分別實(shí)現(xiàn)并區(qū)別兩者的異同):



準(zhǔn)備工作:定義節(jié)點(diǎn)類(lèi)型,一些聲明:

#pragma once

#define ElemType int

#define TRUE    1

#define FALSE   0

#define OK      1

#define ERROR   0

typedef int Status;

typedef int DataType;

//定義結(jié)點(diǎn)類(lèi)型

typedef  struct Node

{

ElemType data;

struct Node  *next;

}SeqNode;

typedef  struct Node *LinkList;            //定義指針類(lèi)型



初始化:



//帶頭結(jié)點(diǎn)的初始化,建立一個(gè)只有頭結(jié)點(diǎn)的空鏈表,頭結(jié)點(diǎn)的數(shù)據(jù)域記錄表長(zhǎng),并且頭結(jié)點(diǎn)不計(jì)入長(zhǎng)度。

//初始化成功返回OK,失敗返回ERROR

Status Init_Head_SeqNode(LinkList *Head)                

{

*Head = (LinkList)malloc(sizeof(SeqNode));

if((*Head) == NULL)

{

printf("out  of  memory\n");

return ERROR;

}

(*Head)->next = NULL;

(*Head)->data = 0;

return OK; 

}

//不帶頭結(jié)點(diǎn)的初始化,建立一個(gè)只有頭結(jié)點(diǎn)的空鏈表

Status  Init_SeqNode(LinkList *Head)

{

*Head = NULL;

return TRUE; 

}



頭插:下邊分別是帶頭結(jié)點(diǎn)與不帶頭結(jié)點(diǎn)的頭插方式,直接上代碼,可能有些抽象,我自己畫(huà)了一些圖,來(lái)幫助理解,希望可以也可以幫助大家理解:


帶頭結(jié)點(diǎn)的頭插:

c語(yǔ)言線(xiàn)性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是什么

不帶頭結(jié)點(diǎn)的頭插:

c語(yǔ)言線(xiàn)性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是什么


頭插代碼:


//帶頭結(jié)點(diǎn)頭插,插入成功返回TRUE,失敗返回ERROR

Status Insert_Head_Fr(LinkList Head,ElemType x)

{

    LinkList new_node;                           //保存新申請(qǐng)的結(jié)點(diǎn)

    new_node = (LinkList)malloc(sizeof(Node));

if(NULL == new_node)

{

    printf("out of memory\n");

    return FALSE;

}

    new_node->data = x;                    //把要插入的值賦值給新申請(qǐng)的結(jié)點(diǎn)的數(shù)據(jù)域

    new_node->next = Head->next;        //第一步:把頭結(jié)點(diǎn)的下一元素即就是首元結(jié)點(diǎn)地地址賦給新的結(jié)點(diǎn)

    Head->next = new_node;                 //第二步:把新申請(qǐng)的結(jié)點(diǎn)賦值給頭結(jié)點(diǎn)  

    (Head->data)++;                  //帶頭結(jié)點(diǎn)的頭節(jié)點(diǎn)的數(shù)據(jù)域用來(lái)保存鏈表的個(gè)數(shù),每添加一個(gè)元素加1

    return TRUE;

}

//不帶頭結(jié)點(diǎn)的頭插,插入成功返回TRUE,失敗返回FALSE

Status Isert_No_Head_Node(LinkList *Head,ElemType x)

{

LinkList new_node;   //保存新申請(qǐng)的結(jié)點(diǎn)

new_node = (LinkList)malloc(sizeof(Node));

if(NULL == new_node)

{

printf("out of memory\n");

return FALSE;

}

new_node->data = x;  

new_node->next = (*Head);           

//第一步:先讓新申請(qǐng)的結(jié)點(diǎn)指向首元結(jié)點(diǎn),因?yàn)椴粠ь^結(jié)點(diǎn)的鏈表頭指針保存首元結(jié)點(diǎn)的地址,那么就需要這樣賦值

(*Head) = new_node;              //第二步:讓頭指針指向新申請(qǐng)的結(jié)點(diǎn)。

           return TRUE;

}



尾插:同樣我也給出一些我自己繪的圖:



帶頭結(jié)點(diǎn)的尾插:

c語(yǔ)言線(xiàn)性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是什么

不帶頭結(jié)點(diǎn)的尾插:

c語(yǔ)言線(xiàn)性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是什么


尾插代碼:


/*不帶頭結(jié)點(diǎn)的與帶頭結(jié)點(diǎn)的進(jìn)行尾插的時(shí)候,有人會(huì)認(rèn)為兩者是沒(méi)有區(qū)別的,

**我想你可能忽略了當(dāng)鏈表中沒(méi)有元素時(shí)兩著的插入還是有區(qū)別的。

*/

//帶頭結(jié)點(diǎn)尾插,插入成功返回TRUE,失敗返回ERROR

Status Insert_Head_Ba(LinkList Head,ElemType  x)

{

LinkList new_node;                            //保存新申請(qǐng)的結(jié)點(diǎn)

LinkList temp = Head;                         //找到尾結(jié)點(diǎn)

new_node = (LinkList)malloc(sizeof(Node));

if(NULL == new_node )

{

printf("out of memory\n");

return FALSE;

}

//利用臨時(shí)變量遍歷所有鏈表,找到尾結(jié)點(diǎn),因?yàn)閠emp本身是指向當(dāng)前節(jié)點(diǎn)的next的,所以當(dāng)temp等于NULL時(shí)就到了鏈表的最后一個(gè)結(jié)點(diǎn)

while(NULL != temp->next)                 

{

temp = temp->next;

}

new_node->data = x;

new_node->next = NULL;

temp->next = new_node;

Head->data++;               //帶頭結(jié)點(diǎn)的頭節(jié)點(diǎn)的數(shù)據(jù)域用來(lái)保存鏈表的個(gè)數(shù),每添加一個(gè)元素加1

return TRUE;

}

//不帶頭結(jié)點(diǎn)尾插,插入成功返回TRUE,失敗返回ERROR

Status Insert_No_Head_Ba(LinkList *Head,ElemType x)

{

LinkList new_node;

LinkList temp = (*Head);                        //保護(hù)頭指針

new_node = (LinkList)malloc(sizeof(Node));      //為新申請(qǐng)的結(jié)點(diǎn)分配空間

if(NULL == new_node)

{

printf("out of menory\n");

return FALSE;

}

if(NULL == (*Head))                    //空鏈表

{

new_node->next = NULL;

new_node->data = x;

(*Head) = new_node;

return TRUE;

}

else

{

//利用臨時(shí)變量遍歷所有鏈表,找到尾結(jié)點(diǎn),因?yàn)閠emp本身是指向當(dāng)前節(jié)點(diǎn)的next的,所以當(dāng)temp等于NULL時(shí)就到了鏈表的最后一個(gè)結(jié)點(diǎn)了

while(NULL != temp->next)             

{

temp = temp->next;

}

new_node->data = x;

new_node->next = NULL;

temp->next = new_node;

return TRUE;

}

}



按照位置插入:同樣先看圖:


帶頭結(jié)點(diǎn)的按位置插入:

c語(yǔ)言線(xiàn)性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是什么

不帶頭結(jié)點(diǎn)按照位置插入:

c語(yǔ)言線(xiàn)性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是什么


//帶頭結(jié)點(diǎn)的按照位置插入如元素,頭節(jié)點(diǎn)不計(jì)入位置,插入時(shí)分為空鏈表和非空鏈表,由于帶頭結(jié)點(diǎn)所以所有操作是一樣的

//插入成功返回TRUE,并且頭結(jié)點(diǎn)的數(shù)據(jù)元素加1,插入失敗返回FALSE。

Status Insert_Head_Pos_SeqNode(LinkList Head, ElemType x, int pos)

{

LinkList temp = Head;                         //保護(hù)頭指針

LinkList temp_pre = Head;                      //保存定位的pos位置地址

LinkList new_node;

new_node = (LinkList)malloc(sizeof(Node));      //為新申請(qǐng)的結(jié)點(diǎn)分配空間

if(NULL == new_node)

{

printf("out of memory\n");

return FALSE;

}

if(pos > Head->data)         

{

printf("插入位置出錯(cuò),%d不能插入\n",x);

return FALSE;

}

//通過(guò)遍歷找到要放數(shù)據(jù)位置的結(jié)點(diǎn),但是由于單鏈表的當(dāng)前結(jié)點(diǎn)只能找到下一個(gè)結(jié)點(diǎn),

//而插入數(shù)據(jù)時(shí),需要知道當(dāng)前結(jié)點(diǎn)的位置,所以就需要定義一個(gè)變量來(lái)保存當(dāng)前前結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn)

for(int i = 0; i < pos;i++)                                

{

temp = temp->next;

temp_pre = temp_pre->next;

}

new_node->data = x;               //為新申請(qǐng)的節(jié)點(diǎn)的數(shù)據(jù)域賦值

new_node->next = temp;          

//第一步:首先讓新結(jié)點(diǎn)指向要插入的位置,也就是當(dāng)前結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn)保存的位置

temp_pre->next = new_node;                 //第二步:讓當(dāng)前結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn)指向指向新結(jié)點(diǎn)

Head->data++;                             //插入成功,鏈表個(gè)數(shù)加1

return TRUE;

}

//不帶頭結(jié)點(diǎn)的按位置插入,分為兩種情況,如果是空鏈表,就要修改頭指針的指向,那么修改指針的指向,就要用二級(jí)指針接收

//如果不是空鏈表,只需要遍歷鏈表,找到位置,這兩種情況都要考慮插入位置是否正確

//插入成功返回TRUE,插入失敗返回FALSE。

Status Inser_No_Head_Pos_SeqNode(LinkList *Head, int pos, ElemType x)

{

int Num = 0;                                 //計(jì)算鏈表一共多少個(gè)結(jié)點(diǎn)

LinkList temp = (*Head);                    //保護(hù)頭指針

        LinkList temp_pre = (*Head);                //保存pos 位置的地址

LinkList new_node;

new_node = (LinkList)malloc(sizeof(Node));      //為新申請(qǐng)的結(jié)點(diǎn)分配空間

if(NULL == new_node )         //防止開(kāi)辟內(nèi)存失敗

{

printf("out of memory\n");

return FALSE;

}

//處理空鏈表的情況

if(NULL == (*Head) )

{

if(pos > 0)

{

printf("插入位置出錯(cuò),%d不能插入\n",x);

return FALSE;

}

else

{

new_node->data = x;                  //為開(kāi)辟的新結(jié)點(diǎn)賦值

new_node->next = NULL;  //第一步:先讓新申請(qǐng)的節(jié)點(diǎn)指向要插入 的結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)

(*Head) = new_node;                  //讓頭指針指向新結(jié)點(diǎn)

return TRUE;

}

}

//處理非空鏈表的情況

else

{

//通過(guò)遍歷找到要放數(shù)據(jù)位置的結(jié)點(diǎn),但是由于單鏈表的當(dāng)前結(jié)點(diǎn)只能找到下一個(gè)結(jié)點(diǎn),

//而插入數(shù)據(jù)時(shí),需要知道當(dāng)前結(jié)點(diǎn)的位置,所以就需要定義一個(gè)變量來(lái)保存當(dāng)前前結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn)

while(NULL != temp)

{

Num++;

temp = temp->next;

}

if(pos+1 > Num)                                //如果插入位置出錯(cuò)直接跳出

{

printf("插入位置出錯(cuò),%d不能插入\n",x);

return FALSE;

}

else if(0 == pos)

{

new_node->data = x;                  //為開(kāi)辟的新結(jié)點(diǎn)賦值

new_node->next = (*Head);

(*Head) = new_node;

}

else

{

//當(dāng)遍歷確定pos位置正確后,此時(shí)幾個(gè)指針的指向已經(jīng)發(fā)生改變,需要重新指向頭指針,遍歷找到需要插入的結(jié)點(diǎn)

temp = *Head;   

for(int i = 0; i < pos - 1; i++)                //定位到要?jiǎng)h除的結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn)

{

temp = temp->next;

}

new_node->data = x;                            //給新結(jié)點(diǎn)的數(shù)據(jù)域賦值

new_node->next = temp->next;     

                   //第一步:首先讓新結(jié)點(diǎn)指向要插入的位置,也就是當(dāng)前結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn)保存的位置

temp->next = new_node;        //  第二步:讓當(dāng)前結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn)指向指向新結(jié)點(diǎn)

}

}

return TRUE;

}



頭刪:對(duì)與刪除操作,與插入操作類(lèi)比,不在畫(huà)圖,兩者是類(lèi)同的。


//不帶頭結(jié)點(diǎn)的頭刪,需要考慮鏈表是否為空鏈表,或者或一個(gè)元素的時(shí)候,當(dāng)只有一個(gè)元素的時(shí)候,頭刪除就需要,修改頭指針的指向,其他地方的刪除,順序都一樣,用x放回刪除的數(shù)據(jù)

//刪除成功返回TRUE,失敗返回FALSE

Status Delite_No_Head_SeqNode(LinkList *Head,ElemType *x)

{

LinkList temp_node = (*Head);            //防止頭指針被修改

if(NULL == temp_node)

{

printf("鏈表已空,已經(jīng)沒(méi)有元素可以刪除了\n");

return FALSE;

}

if(NULL == temp_node->next)

{

*x = temp_node->data;            //把要?jiǎng)h除的結(jié)點(diǎn)的值保存的x中去

(*Head) = NULL;

free(temp_node);                //釋放刪除的結(jié)點(diǎn),防止內(nèi)存泄露

            temp_node = NULL; 

                return TRUE;

}

else                                  //處理鏈表中有一個(gè)以上的結(jié)點(diǎn)的刪除

{

*x = temp_node->data;               //把要?jiǎng)h除的結(jié)點(diǎn)的值保存的x中去

*Head = temp_node->next;             //修該頭指針的指向

free(temp_node);               //釋放刪除的結(jié)點(diǎn),防止內(nèi)存泄露

temp_node = NULL;  

                return TRUE;

}

}

//帶頭結(jié)點(diǎn)的頭刪,不論是有一個(gè)元素還是多和元素,刪除操作都不需要修該頭指針指向,因而也就不需要修該頭指針指向,用x放回刪除的數(shù)據(jù)

//刪除成功返回TRUE,失敗返回FALSE;

Status Delite_Head_Fr_SeqList(LinkList Head,ElemType *x)

{

LinkList temp = Head->next;        //定義臨時(shí)變量防止頭指針被修改

if(NULL == temp->next)

{

printf("鏈表已空,已經(jīng)沒(méi)有元素刪除\n");

return FALSE;

}

*x = temp->next->data;            //把要?jiǎng)h除的結(jié)點(diǎn)的值保存的x中去

temp = temp->next;                //第一步:讓臨時(shí)結(jié)點(diǎn)指向要?jiǎng)h除的結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)

free(Head->next);               //第二步:釋放首元結(jié)點(diǎn)的內(nèi)存,防止內(nèi)存泄露

Head->next = temp;              //第三步:修改頭指針的指向

return TRUE;

}



尾刪:同樣也不在給出示意圖:對(duì)比尾插的圖。



//帶頭結(jié)點(diǎn)的尾刪,因?yàn)橛蓄^結(jié)點(diǎn)所有操作都一樣

Status Delite_Head_Br_SeqNode(LinkList Head,ElemType *x)

{

//定義臨時(shí)變量防止頭指針被修改  ,首先讓指向首元結(jié)點(diǎn),尾刪用它來(lái)定位最后一個(gè)結(jié)點(diǎn),

//由于單鏈表,只知道當(dāng)前節(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)的位置,那么,就需要定義一個(gè)變量保存當(dāng)前結(jié)點(diǎn)的地址 

LinkList temp = Head->next;          //定位最后一個(gè)指針     

LinkList temp_node_pre = Head;        //保存最后一個(gè)結(jié)點(diǎn)的地址

if(NULL == temp)

{

printf("鏈表已空,已經(jīng)沒(méi)有元素刪除\n");

return FALSE;

}

while(NULL != temp->next)

{

temp = temp->next;

temp_node_pre = temp_node_pre->next;

}

*x = temp->data;                      //保存最后一個(gè)結(jié)點(diǎn)的數(shù)據(jù)域的值

temp_node_pre->next = NULL;                 //修改原來(lái)結(jié)點(diǎn)的倒數(shù)第二個(gè)結(jié)點(diǎn)的指向

free(temp);           //此時(shí)temp_node指向最后一個(gè)結(jié)點(diǎn),防止內(nèi)存泄露,釋放最后一個(gè)結(jié)點(diǎn)的內(nèi)存

temp =NULL;

return TRUE;

}

//不帶頭結(jié)點(diǎn)的尾刪,由于當(dāng)鏈表只有一個(gè)元素時(shí),刪除最后一個(gè)結(jié)點(diǎn)就要修改指針指向,因而就要用二級(jí)指針接收頭指針,用x放回刪除的數(shù)據(jù)

//刪除成功返回TRUE,失敗返回FALSE;

Status Delite_No_Head_Br_SeqNode(LinkList *Head,ElemType *x)

{

//定義臨時(shí)變量防止頭指針被修改  ,首先讓指向首元結(jié)點(diǎn),尾刪用它來(lái)定位最后一個(gè)結(jié)點(diǎn),

//由于單鏈表,只知道當(dāng)前節(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)的位置,那么,就需要定義一個(gè)變量保存當(dāng)前結(jié)點(diǎn)的地址 

LinkList temp_node = (*Head)->next;

LinkList  temp_node_pre = (*Head);

if(NULL == (*Head))

{

printf("鏈表已空,已無(wú)元素可以刪除\n");

return FALSE;

}

while(NULL != temp_node->next)

{

temp_node = temp_node->next;

temp_node_pre = temp_node_pre->next;

}

*x = temp_node->data;                        //保存最后一個(gè)結(jié)點(diǎn)的數(shù)據(jù)域的值

temp_node_pre->next = NULL;                 //修改原來(lái)結(jié)點(diǎn)的倒數(shù)第二個(gè)結(jié)點(diǎn)的指向

free(temp_node);      //此時(shí)temp_node指向最后一個(gè)結(jié)點(diǎn),防止內(nèi)存泄露,釋放最后一個(gè)結(jié)點(diǎn)的內(nèi)存

return TRUE;

}

//帶頭結(jié)點(diǎn)的按照位置刪除,首先要考慮刪除的位置是否存在,然后由于帶頭結(jié)點(diǎn),所以無(wú)論是一個(gè)元素,還是多個(gè)元素刪除操作都一樣

Status Delite_Head_Pos_SeqNode(LinkList Head,int pos, ElemType *x)

{

//定義臨時(shí)變量防止頭指針被修改  ,首先讓指向首元結(jié)點(diǎn),尾刪用它來(lái)定位最后一個(gè)結(jié)點(diǎn),

//由于單鏈表,只知道當(dāng)前節(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)的位置,那么,就需要定義一個(gè)變量保存當(dāng)前結(jié)點(diǎn)的地址 

LinkList temp = Head->next;     //定位最后一個(gè)指針需要?jiǎng)h除的結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn)     

LinkList temp_node_pre = Head;        //保存即將刪除的結(jié)點(diǎn)的地址

if(NULL == temp)

{

printf("鏈表已空,已經(jīng)沒(méi)有元素刪除\n");

return FALSE;

}

if(pos > temp_node_pre->data )                  //判斷刪除的位置是否存在

{

printf("刪除位置出錯(cuò)\n");

return FALSE;

}

for(int i = 0; i < pos-1;i++)                  //遍歷鏈表找到鏈表要?jiǎng)h除的結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn)

{

temp = temp->next;                      //定位要?jiǎng)h除的位置

}

*x = temp->next->data;                          //用x返回需要?jiǎng)h除結(jié)點(diǎn)的值

temp_node_pre = temp->next;

temp->next = temp->next->next;                   //讓刪除的前一個(gè)結(jié)點(diǎn)指向要?jiǎng)h除的下一個(gè)結(jié)點(diǎn)

free(temp_node_pre);                     //此時(shí)temp_node指向刪除的結(jié)點(diǎn),防止空間泄露,釋放內(nèi)存

temp_node_pre = NULL;

Head->data--;                                    //頭結(jié)點(diǎn)保存著鏈表的長(zhǎng)度,刪除以后減去一個(gè)

return TRUE;

}



按照位置刪除:同樣也不在給出示意圖:對(duì)比按照位置刪除的圖。



//不帶頭結(jié)點(diǎn)按照位置刪除,由于當(dāng)只有一個(gè)結(jié)點(diǎn)的刪除需要修改頭指針指向需要特別處理

Status Delite_No_Head_Pos_SeqNode(LinkList *Head, int pos, ElemType *x)

{

int NUM = 0;                //統(tǒng)計(jì)一共鏈表一共多少個(gè)結(jié)點(diǎn)

//定義臨時(shí)變量防止頭指針被修改  ,首先讓指向首元結(jié)點(diǎn),尾刪用它來(lái)定位最后一個(gè)結(jié)點(diǎn),

//由于單鏈表,只知道當(dāng)前節(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)的位置,那么,就需要定義一個(gè)變量保存當(dāng)前結(jié)點(diǎn)的地址 

LinkList temp = (*Head);

if(NULL == temp)

{

printf("鏈表已空,已無(wú)元素可以刪除\n");

return FALSE;

}

else if(NULL == temp->next)        //處理只有一個(gè)結(jié)點(diǎn)的情況

{

*x = temp->data;          //用x返回需要?jiǎng)h除結(jié)點(diǎn)的值

(*Head) = NULL;                    //頭結(jié)點(diǎn)置空

free(temp);                 //釋放第一個(gè)結(jié)點(diǎn)的空間,防止內(nèi)存泄露

temp = NULL;                   //防止指向非法空間

return TRUE;

}

else

{

while(NULL != temp)

{

NUM++;

temp = temp->next;

}

if(pos > NUM)

{

printf("刪除位置出錯(cuò)");

return FALSE;

}

if(0 == pos)

{

temp = *Head;  

*x = temp->data;

*Head = temp->next;

free(temp);

temp = NULL;

}

else

{

//當(dāng)遍歷確定pos位置正確后,此時(shí)幾個(gè)指針的指向已經(jīng)發(fā)生改變,需要重新指向頭指針,遍歷找到需要插入的結(jié)點(diǎn)

temp = *Head;   

for(int i = 0; i < pos-1; i++)

{

temp = temp->next;

}

*x = temp->next->data;                     //用x返回需要?jiǎng)h除結(jié)點(diǎn)的值

LinkList free_node = temp->next;           //free_node用與保存即將刪除的結(jié)點(diǎn)

temp->next = temp->next->next; 

free(free_node);                       //釋放第一個(gè)結(jié)點(diǎn)的空間,防止內(nèi)存泄露

free_node = NULL;

}

}

return TRUE;

}



打印輸出所有數(shù)據(jù):



//帶頭結(jié)點(diǎn)打印輸出所有數(shù)據(jù)

Status Show_Node(LinkList Head)

{

LinkList temp = Head->next;

while(NULL != temp)

{

printf("%d  ",temp->data);

temp = temp->next;

}

printf("\n");

return TRUE;

}

//不帶頭結(jié)點(diǎn)打印輸出所有數(shù)據(jù)

Status Show_Node_No_Head(LinkList Head)

{

LinkList temp = Head;

while(NULL != temp)

{

printf("%d  ",temp->data);

temp = temp->next;

}

printf("\n");

return TRUE;

}



清空鏈表:釋放所有有效結(jié)點(diǎn),對(duì)于帶頭結(jié)點(diǎn)鏈表,要把頭結(jié)點(diǎn)的 數(shù)據(jù)域置0



//不帶頭結(jié)點(diǎn)的清空鏈表,釋放所有的結(jié)點(diǎn)

Status Clean_No_Head_SeqNode(LinkList *Head )

{

LinkList temp_node = *Head;

LinkList temp_node_pre = *Head;

*Head = NULL;

while(NULL != temp_node)

{

temp_node = temp_node->next;        //因?yàn)轭^結(jié)點(diǎn)不空,讓臨時(shí)指針指向下一個(gè)結(jié)點(diǎn)

free(temp_node_pre);               //釋放第一結(jié)點(diǎn)的空間

temp_node_pre = temp_node;         //指向下一個(gè)空間

}

return TRUE;

}

//帶頭結(jié)點(diǎn)的清空鏈表,釋放除頭結(jié)點(diǎn)以外的空間

Status Clean_Head_SeqNode(LinkList Head)

{

LinkList temp_node = Head->next;

LinkList temp_node_pre = Head->next;

Head->next = NULL;

Head->data = 0;

while(NULL != temp_node->next)

{

temp_node = temp_node->next;

free(temp_node_pre);

temp_node_pre = temp_node;

}

return TRUE;

}



排序:對(duì)于排序,首先可以采用各種排序方法,然后就是排序過(guò)程中,我提一點(diǎn)就是只需要把值交換并不需要交換結(jié)點(diǎn)。這里采用冒泡排序。



//排序,由于只需要交換兩個(gè)鏈表中的值就好了,不用修改指針指向所以帶與不帶頭結(jié)點(diǎn)操作差不多,只是有細(xì)微的差別

Status Sort_No_Head_SeqNode(LinkList Head)

{

LinkList temp_node_i = Head;

LinkList temp_node_j = Head;

LinkList temp_node_pre = Head;

ElemType temp;                        //用與交換值

if(NULL == temp_node_i)

{

printf("鏈表為空,無(wú)法排序\n");

return FALSE;

}

for(temp_node_i = temp_node_i->next; NULL != temp_node_i; temp_node_i = temp_node_i->next)

{

for( temp_node_j = temp_node_j; NULL != temp_node_j;  temp_node_j = temp_node_j->next)

{

if(temp_node_j->data > temp_node_pre->data)

{

temp = temp_node_j->data;

temp_node_j->data = temp_node_pre->data;

temp_node_pre->data = temp;

temp_node_pre = temp_node_pre->next;

}

temp_node_pre = temp_node_pre->next;

}

}

return TRUE;

}

//排序帶頭結(jié)點(diǎn)

Status Sort_Head_SeqNode(LinkList Head)

{

LinkList temp_node_i = Head->next;

LinkList temp_node_j = Head->next;

LinkList temp_node_pre = Head->next;

ElemType temp;                                              //用與交換值

if(NULL == temp_node_i)

{

printf("鏈表為空,無(wú)法排序\n");

return FALSE;

}

for(temp_node_i = temp_node_i; NULL != temp_node_i->next; temp_node_i = temp_node_i->next)

{

for(temp_node_j = Head; NULL != temp_node_j->next; temp_node_j = temp_node_j->next)

{

if(temp_node_j->data > temp_node_j->next->data)

{

temp = temp_node_j->next->data;

temp_node_j->next->data = temp_node_j->data;

temp_node_j->data = temp;

}

}

}

return TRUE;

}



    以上對(duì)單鏈表帶頭結(jié)點(diǎn)與不帶頭結(jié)點(diǎn)的頭插、尾插、按照位置插、頭刪、尾刪、按照位置刪除、清空鏈表、排序、打印輸出做了盡可能詳盡的注釋?zhuān)甲隽藴y(cè)試,但是沒(méi)有給出主函數(shù),數(shù)據(jù)結(jié)構(gòu)中,這里不是重點(diǎn),并且限于篇幅,因而沒(méi)有給出主函數(shù)。當(dāng)然以上代碼只是我的理解,大家可以如果發(fā)現(xiàn)那塊有錯(cuò)誤,希望指正。


    最后,細(xì)心的大家會(huì)發(fā)現(xiàn)這里邊有好多重發(fā)的代碼:比如生成新結(jié)點(diǎn),定位要插入刪除的位置,有好多重復(fù)的代碼,那么就可以把它寫(xiě)成一個(gè)函數(shù),簡(jiǎn)化代碼,更有,這種結(jié)構(gòu)的結(jié)構(gòu)體,操作起來(lái)有些不方便,如果采用下邊這種結(jié)構(gòu),更會(huì)簡(jiǎn)化,并且便于理解。


typedef struct node  //節(jié)點(diǎn)類(lèi)型

{

type value;

struct node *next;

}Node;

typedef struct list

{

Node *phead;

Node *ptail;

}List;

感謝各位的閱讀,以上就是“c語(yǔ)言線(xiàn)性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是什么”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)c語(yǔ)言線(xiàn)性表的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是什么這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI