日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【数据结构基础笔记】【链表】

發布時間:2023/12/1 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【数据结构基础笔记】【链表】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

代碼參考《妙趣橫生的算法.C語言實現》

文章目錄

  • 前言
    • 1、鏈表基礎
    • 2、創建一個鏈表
    • 3、插入結點
    • 4、刪除結點
    • 5、銷毀鏈表
    • 6、實例分析


前言

本章總結:鏈表的定義、創建、銷毀,結點的插入與刪除


1、鏈表基礎

鏈表的物理存儲結構是用一組地址任意的存儲單元存儲數據的。
在鏈表結構中,每個數據元素記錄都存放在鏈表的一個結點node中,而每個結點之間由指針將其連接到一起。
每個結點由指針域(存放后繼結點的位置)、數據域構成。
一個鏈表通常有一個表頭,是一個指針變量,用來存放第一個結點地址。
鏈表的最后一個結點的的指針域要置空,表示為鏈表的尾結點。

鏈表特點:
1、每個結點包括兩個部分:數據域和指針域
數據域用來存放數據元素本身信息,指針域用來存放后繼結點的地址
2、鏈表邏輯上是連續的,但物理上不一定是連續存儲結點。
3、只要獲取鏈表的頭結點,就可以通過指針遍歷整條鏈表
一個鏈表結點可以描述為:

typedef struct node{ElemType data; //數據域struct node *next; //指針域 }LNode,*LinkList;

每個結點的類型是LNode
*LinkList是指向LNode類型數據的指針類型定義。
所以 LNode *L 與 LinkList L; 是等價的。

2、創建一個鏈表

LinkList GreatLinkList(int n) {//建立一個長度為n的鏈表LinkList p,r,list=NULL; //p:相當于每次新建結點的暫存器,r:相當于插入結點的上一個結點,永遠指向原先鏈表的最后一個結點。list鏈表的頭指針ElemType elem; //獲取暫存數據int i; //定義累加器for(i=0;i<n;i++){scanf("%d",&elem);p=(LinkList)malloc(sizeof(LNode)); //分配內存,并將首地址送到pp->data=elem; //置入數據p->next =NULL; //指針指向NULL,暫時不考慮下一個結點if(!list) //如果鏈表為空,則新創建的結點就是該鏈表的第一個結點list=p;else //如果鏈表不為空,則將新建立的結點連接到之前鏈表的尾部r->next=p;r=p; //將p結點的數據賦給r}return list; //將鏈表的頭指針返回主調函數,通過list就可以訪問鏈表中的每個結點,并進行操作 }

3、插入結點

步驟描述:
1、創建新節點,用指針p指向該結點
2、將q指向結點的next域的值賦值給p指向結點的next域
3、將p的值賦值給q的next域

代碼描述:

void insertList(LinkList *list,LinkList q,ElemType e) {//向鏈表中由指針q指向的結點后面插入結點,結點數據位eLinkList p;p=(LinkList)malloc(sizeof(LNode)); //生成一個新節點,由p指向它p->data=e;if(!*list) //如果鏈表為空{*list=p;p->next=NULL;} //當鏈表為空的時候,q沒有意義,只能在頭結點后面插入第一個元素else{//當鏈表不為空的時候,認為q指向的結點一定存在//將q指向的結點的next域的值賦給p指向的結點的next域p->next=q->next;q->next=p; } }

通過這個算法同樣可以創建一個鏈表,因為鏈表為空時,list==NULL,可以自動創建一個結點。在下面創建其他結點時,只要始終將指針q指向鏈表的最后一個結點,就可以創建出一個鏈表

4、刪除結點

從非空鏈表中刪除q所指的結點。
考慮三個情況:1、q指向的是鏈表的第一個結點
2、q指向的結點的前驅結點的指針已知
3、q指向的結點的前驅結點的指針未知
步驟:
1:將q所指的結點的指針域next的值賦給頭指針list,讓list指向第二個結點,再釋放掉q所指的結點即可。
2:假設前驅指針為r,將q所指的結點的指針域next的值賦給r的指針域next,釋放掉q所指結點
3:當q所指的結點的前驅結點的指針未知,需要通過鏈表頭指針list遍歷鏈表,找到q的前驅結點,并將該指針賦值給變量r,再按照第二種情況去做即可

情況1、2的代碼描述:

void delLink(LinkList *list,LinkList r,LinkList q) {if(q==*list) //情況1:q指向鏈表的第一個結點*list=q->next;else //情況2:q指向的結點前驅結點的指針已知r->next=q->next;free(q); }

情況1、3的代碼描述:

void delLink(LinkList *list,LinkList r,LinkList q) {if(q==*list)//情況1:q指向鏈表的第一個結點{*list=q->next; free(q);}else //情況3:q指向的結點前驅結點的指針未知{for(r=*list;r->next!=q;r=r->next); //遍歷鏈表,找到q的前驅結點的指針if(r->next!=NULL){r->next=q->next; //從鏈表中刪除q指向的結點free(q);}} }

5、銷毀鏈表

使用鏈表之后需要銷毀它,因為鏈表本身會占用內存。
code描述:

void destroyLinkList(LinkList *list) {LinkList p,q;p=*list;while(p){q=p->next;free(p);p=q;}*list=NULL; }

6、實例分析

要求:
輸入一組整數(大于10個數),以0作為結束標志,將這組整數存放到一個鏈表中(結束標志0不包括在內),打印出該鏈表中的值。然后刪除該鏈表中的第5個元素,打印出刪除后的結果。最后在內存中釋放掉該鏈表。

#include "stdio.h" #include "malloc.h" #include "conio.h"typedef int ElemType; //指針定義 typedef struct node {ElemType data; //數據域struct node* next; //指針域 }LNode, * LinkList;//***********創建鏈表******************// // LinkList GreatLinkList(int n) {//建立一個長度為n的鏈表LinkList p, r=NULL, list = NULL; //p:相當于每次新建結點的暫存器,r:相當于插入結點的上一個結點,永遠指向原先鏈表的最后一個結點。list鏈表的頭指針ElemType elem; //獲取暫存數據int i; //定義累加器for (i = 0;i < n;i++){scanf("%d", &elem);p = (LinkList)malloc(sizeof(LNode)); //分配內存,并將首地址送到pp->data = elem; //置入數據p->next = NULL; //指針指向NULL,暫時不考慮下一個結點if (!list) //如果鏈表為空,則新創建的結點就是該鏈表的第一個結點list = p;else //如果鏈表不為空,則將新建立的結點連接到之前鏈表的尾部r->next = p;r = p; //將p結點的數據賦給r}return list; //將鏈表的頭指針返回主調函數,通過list就可以訪問鏈表中的每個結點,并進行操作 }//*************插入結點************// // void insertList(LinkList* list, LinkList q, ElemType e) {//向鏈表中由指針q指向的結點后面插入結點,結點數據位eLinkList p;p = (LinkList)malloc(sizeof(LNode)); //生成一個新節點,由p指向它p->data = e;if (!*list) //如果鏈表為空{*list = p;p->next = NULL;} //當鏈表為空的時候,q沒有意義,只能在頭結點后面插入第一個元素else{//當鏈表不為空的時候,認為q指向的結點一定存在//將q指向的結點的next域的值賦給p指向的結點的next域p->next = q->next;q->next = p;} } //通過這個算法同樣可以創建一個鏈表,因為鏈表為空時,list==NULL,可以自動創建一個結點。在下面創建其他結點時,只要始終將指針q指向鏈表的最后一個結點,就可以創建出一個鏈表//刪除結點 void delLink(LinkList* list, LinkList q) {LinkList r;if (q == *list)//情況1:q指向鏈表的第一個結點{*list = q->next;free(q);}else //情況3:q指向的結點前驅結點的指針未知{for (r = *list;r->next != q;r = r->next); //遍歷鏈表,找到q的前驅結點的指針if (r->next != NULL){r->next = q->next; //從鏈表中刪除q指向的結點free(q);}} }//銷毀鏈表 void destroyLinkList(LinkList* list) {LinkList p, q;p = *list;while (p){q = p->next;free(p);p = q;}*list = NULL; }void print_linklist(LinkList show_list) {while (show_list){printf("%d ",show_list->data);show_list = show_list->next;} } int main() {int elem = 0; //定義中間變量數據int i = 0; //定義累加器LinkList L, q; q = L = GreatLinkList(1); //創建1個鏈表結點,q和L指向該結點scanf("%d",&elem);while (elem) //循環地輸入數據,同時插入新生成的結點,結束條件:輸入數據為0{insertList(&L,q,elem);q = q->next;scanf("%d", &elem);}q = L;printf("The content of the linklist\n");print_linklist(q);q = L;printf("\n Delete the fifth element\n");for (i=0;i<4;i++) //將指針q指向第五個元素{if (q == NULL) //確保此時鏈表的長度大于等于5,否則是非法操作{printf("The length of the linklist is smaller than 5");_getche();return 0;}q = q->next;}delLink(&L,q);q = L;print_linklist(q);destroyLinkList(&L);return 0; }

result:

總結

以上是生活随笔為你收集整理的【数据结构基础笔记】【链表】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。