C語言連結串列:遍歷,頭插,尾插,中間插入;頭節點刪除,尾節點刪除,中間刪除的操作
/********************************************************************************************************************************************************************
內容:指標的建立步驟與遍歷
建立的步驟:1、定義連結串列結構體(結構體至少要包括成員的值還有下一個成員元素的指標,如果是雙鏈表,還要包括前一個元素的指標)
2、申請堆記憶體
3、清理堆記憶體
4、給連結串列結構體初始化
建立一個結構體的函式的返回值一般是這個函式結構體的指標,這樣方便我們對這個結構體進行一系列的操作,遍歷、插入
刪除節點等操作。
頭節點:一般在建立一個連結串列,都會建立一個頭節點,用來記錄這個連結串列的節點數。這個節點不用來進行元素的賦值。我們真正開始進行連結串列資料操作的是頭節點的下一個。
插入新節點步驟:
1、建立要插入新節點
2、將新節點中元素的值進行初始化
3、新節點放在原連結串列最後一個元素的下一個元素的位置
4、將新節點的下一個元素設定為NULL
5、將新節點接在最後一個節點的後面
尾插節點法:
1、先找到最後一個不為空節點的位置
2、將新節點插在最後一個節點的後一個
頭插入新節點法:
1、定義一箇中間變數來暫時寄存插入位置後面的元素
2、插入新節點元素
3、將新增的節點與頭節點關聯起來
中間某一個位置插入節點:(注意先後循序:要先儲存後面的元素,在插入;如果先插入,那麼後面的連結串列元素就丟失了)
1、遍歷連結串列,找到要插入節點的位置
2、定義一個指標,用來表示當前節點位置
3、定義一箇中間變數,存放插入節點後面的連結串列元素
4、插入新節點
5、後面節點和新插入節點相關聯起來
頭節點第一個元素刪除法:
1、定義一箇中間變數來暫時寄存要刪除節點後面的連結串列元素
2、刪除節點(free()函式)
3、將剩餘的節點與重新關聯起來
刪除中間某一個值的節點:
1、遍歷連結串列,找到要刪除節點的位置
2、定義一個變數來寄存刪除節點位置前一個元素的指標
3、刪除節點
4、將刪除前一個元素的指標與刪除後的一個節點關聯起來
刪除尾節點:
1、遍歷連結串列,找到尾節點的位置
2、將尾節點的前一個元素指向的下一個元素指為NULL即可
說明:在main函式裡面開啟要進行的操作:尾插入、中間刪除....的操作來驗證,步驟是先建立一個連結串列,再在原來連結串列的基礎上進行相應的操作。
實際需求看個人要驗證的結果來呼叫工程的那個函式。
編譯說明: gcc testlink.c得到a.out可執行檔案,執行./a.out即可。
下例是進行刪除中間值為4的連結串列的執行結果:
********************************************************************************************************************************************************************/
#include <stdio.h> #include <stdlib.h> #include <strings.h> //函式宣告 struct node *creatlink(); void traverse(struct node *Head); void insert_tail(struct node *Head); void delete(struct node *Head); void delete_head(struct node *Head); void insert_head(struct node *Head); void middle_insert(struct node *Head); void delete_tail(struct node *Head); void delete_middle(struct node *Head); //定義連結串列 struct node { int member; //連結串列的成員 struct node *pNext; //連結串列的下一個元素 }; //建立連結串列 struct node *creatlink() { int val; int i=0,len; int cnt =0; struct node *Head = (struct node *)malloc(sizeof(struct node)); //定義一個頭節點,併為其申請堆記憶體空間 bzero(Head,sizeof(struct node)); //清理申請得到的堆記憶體,防止殘留資料干擾 struct node *tail =Head; //頭節點與最後一個節點相關起來 tail -> pNext=NULL; printf("請輸入節點的個數:"); scanf("%d",&len); for(;i<len;i++) //開始建立連結串列 { struct node *new =(struct node *)malloc(sizeof(struct node )); scanf("%d",&val); new -> member = val; //成員的值 tail -> pNext =new; //將新插入的new放在上次最後一個元素的下一個 new -> pNext =NULL; //new插入的最後一個元素的下一個設定為NULL tail = new; //將new新連結串列與tail連在一起 cnt++; //驗證插入的個數是否一致 } Head ->member =cnt; printf("輸出的節點數 %d\n",cnt); return Head; //返回頭節點的指標 } //連結串列的遍歷 //將頭節點的指標傳過來 void traverse(struct node *Head) //每次遍歷從連結串列的頭開始遍歷 { struct node *p = Head->pNext; //這裡值得注意,因為第一個是頭節點,我們遍歷的是從第二個節點開始,才是有效的。所以是Head->pNext開始 while(NULL != p) { printf(" %d ",p->member); printf("->"); p = p->pNext; } if(p==NULL) { printf("NULL"); } printf("\n"); return; } //從尾部插入一個節點 void insert_tail(struct node *Head) { struct node *p=(struct node *)malloc(sizeof(struct node)); //struct node *p =Head; p = Head; //將連結串列的首地址傳給p struct node *insert=(struct node *)malloc(sizeof(struct node)); bzero(insert, sizeof(struct node)); insert->member=9; insert->pNext=NULL; //traverse(p); //保持原來的不變 printf("core in inser insert->member =%d\n",insert->member); while(NULL != p->pNext) //尋找下一個元素為NULL的元素的位置 { p=p->pNext; } p->pNext=insert; //p = insert; traverse(Head); //每次從頭開始遍歷,這裡必須給連結串列的頭指標(傳p的指標的話,只能看到最後一個節點的值) printf("core in insert after while\n"); return; } //從頭部插入新一個節點 void insert_head(struct node *Head) { struct node *p=(struct node*)malloc(sizeof(struct node)); struct node *before_add=(struct node*)malloc(sizeof(struct node)); struct node *insert=(struct node*)malloc(sizeof(struct node)); //要插入的節點 p = Head; //將連結串列的首地址傳給p insert -> member =8; //要插入的值 before_add =p->pNext; //用中間變數儲存插入前後面的資料不會丟失 p->pNext=insert; //插入要插入的新節點 insert->pNext = before_add; //插入後與新節點關聯起來 traverse(Head); } //從連結串列中間插入一個新節點(某一個元素的值為標誌) void middle_insert(struct node *Head) { struct node *p=(struct node*)malloc(sizeof(struct node)); struct node *before_add=(struct node*)malloc(sizeof(struct node)); struct node *insert=(struct node*)malloc(sizeof(struct node)); struct node *pcur=(struct node*)malloc(sizeof(struct node)); //當前節點位置 p = Head; //將連結串列的首地址傳給p int i=3; while(NULL != p->pNext) { pcur = p; //寄存p沒有走向下一個節點的指標 p = p->pNext; if(pcur->member == 3) //在節點等於3的位置後面插入一個節點,值等於7 { before_add =pcur->pNext; //用一箇中間變數寄存3節點後面的連結串列,防止資料丟失 insert -> member = 7; pcur ->pNext =insert; //插入新節點 pcur->pNext->pNext =before_add; //將後面的連結串列元素與插入新節點元素關聯起來 break; } } traverse(Head); } //從頭部將第一個節點刪除掉(前面多了一個0出來) void delete_head(struct node *Head) { struct node *p=(struct node*)malloc(sizeof(struct node)); struct node *before_delete=(struct node*)malloc(sizeof(struct node)); p = Head; //將連結串列的首地址傳給p before_delete = p->pNext; //先用一個變數來存放要刪除節點後邊元素的成員 free(p->pNext); //刪除第一個節點 p = before_delete; //將後面剩下的重新與頭節點相關連起來 traverse(Head); return; } //刪除尾節點 void delete_tail(struct node *Head) { struct node *p=(struct node*)malloc(sizeof(struct node)); struct node *delete=(struct node*)malloc(sizeof(struct node)); struct node *pcur=(struct node*)malloc(sizeof(struct node)); //當前節點位置 p = Head; //將連結串列的首地址傳給p while(NULL != p->pNext) { pcur =p; p=p->pNext; } pcur->pNext=NULL; //前一個節點的下一個元素就是NULL free(p); traverse(Head); } //刪除中間的某一個節點 void delete_middle(struct node *Head) { struct node *p=(struct node*)malloc(sizeof(struct node)); struct node *delete=(struct node*)malloc(sizeof(struct node)); struct node *pcur=(struct node*)malloc(sizeof(struct node)); //當前節點位置 p = Head; delete->member=4; while(NULL != p->pNext) { pcur = p; //寄存p沒有走向下一個節點的指標(前一個節點) p = p->pNext; if(p->member==delete->member) { pcur->pNext=p->pNext; //將刪除節點的前後節點關聯起來 free(p); break; } } traverse(Head); } int main(void) { struct node *pHead = NULL; //定義一個結構體指標 struct node *insert_pHead = NULL; pHead = creatlink(); //將已經建立在堆記憶體中的連結串列的指標存放在pHead中 printf("你輸入的資料是:"); traverse(pHead); //遍歷連結串列,將要遍歷的連結串列的指標傳給它,這裡就決定了建立連結串列的時候為什麼要返回的型別是連結串列指標 printf("進行操作後的連結串列為:\n"); //insert(pHead); //insert_head(pHead); //middle_insert(pHead); //delete_head(pHead); //delete_tail(pHead); delete_middle(pHead); return 0; }