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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

数据结构之:链表详解

發布時間:2024/4/18 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构之:链表详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

鏈表是 數據結構中很重要的基礎 部分,下面 我通過簡單的故事來將鏈表的內容串起來解釋一下,同時也是總結一下自己的學習內容:

故事:

某一天,樂樂,豐豐,呆子,星星,領領,小韋6位小朋友帶領著8個小朋友一起去山上玩耍。當玩耍過后,天下起了大雨 !!于是 14位小朋友趕緊返回,不幸的是山口處山洪暴發。如果想要 過去,14位 小朋友需要連在一起,單個過河的小朋友會被山洪沖走(因為經過試驗證明了這一點,而且小韋在試驗過程中被洪水沖走了) 。

我們將每位小朋友看做是一個節點。

typedef struct Lnode {int data; //小朋友數據struct Lnode *next; //指向下一個小朋友的指針 };

建立單鏈表:

那么要從洪水中過去的話,14位小朋友需要建立一個長隊。可以想到,建立長隊的方法有兩種:

首先我們需要空出來一塊場地用來建立我們的長隊(所說的建立 一個空鏈表)

code:

void InitList(LinkList*&L) {L = (LinkList *)malloc(sizeof(LinkList));L->next = NULL; }

第一種:樂樂站在第一個,星星站在樂樂 的前面,呆子站在星星的前面……依次排列,這樣樂樂會最終站在隊尾(這就是頭插法建立單鏈表)。

? ? ? ? ? ? ? ?1. 2 .3.……豐豐,呆子,星星,樂樂。

code:

void CreateListH(LinkList *&L, int a[], int n)? ?//頭插法建立單鏈表 {LinkList *s;? ? ? ? ? ? ? ? ? ? ? ? ? ? //s是要插入的小朋友int i;L = (LinkList *)malloc(sizeof(LinkList)); //申請空間,L->next = NULL;? ? ? ? ? ? ? ? ? ? ? ? ? //剛開始的時候為空,因為還沒有排隊。for (i = 0; i < n; i++)? ? ? ? ? ? ? ? ?//我們將后來的小朋友插入前面,并讓這個的小朋友的手拉著站在他后面的小朋友的衣服{s = (LinkList *)malloc(sizeof(LinkList));s->data = a[i];s->next = L->next;?L->next = s;} }



第二種:樂樂站在第一個,星星 站在樂樂的后面,呆子站在星星的后面,豐豐站在呆子的后面,……其他人依次后排(這就是尾插法建立單鏈表)。

? ? ? ? ? ? ? ?樂樂,星星,呆子,豐豐……。

Code:

void? CreateListR(LinkList *&L, int a[], int n) {int i;LinkList *s, *r;L = (LinkList *)malloc(sizeof(LinkList));? //申請空間r = L;for (i = 0; i < n; i++)? ? ? // s是要插入的小朋友,r只是一個臨時標記,為了知道現在誰在最后的位置{s = (LinkList *)malloc(sizeof(LinkList));s->data = a[i];r->next = s;? ? ? ? ? ? //將 s小朋友插入r的后面,r = s;? ? ? //插入后,那么s在最后的位置,讓其成為標記。因為我們需要知道誰在最后面,方面下次的插入操作}r->next = L->next;? ? ? ? ? ? ?//隊伍建立完成后,最后? 隊尾節點為 NULL; }



那么現在隊伍建立完成了,可以過河了,小朋友們都很高興(其實 一點都不高興)。

這個時候小韋竟然回來了,小朋友們都很高興他還 或活著,選舉他當了隊長 。由于小韋剛回來 ,對隊伍的情況 不是 很了解,他想要知道隊伍有多少人,于是他從隊伍的頭到尾進行了查數:

(單鏈表中數據 節點 的個數)

code:

int ListLength(LinkList *L) {int ans = 0;LinkList *p = L; //小韋學長找到了隊伍頭部 while (p->next != NULL) //直到尾部,看到一個小朋友 就ans++;{ans++;p = p->next;}return ans; }
但是 悲劇的是,小韋由于智商有限,只能數到10,就不會數了。于是他想了一個方法,讓隊伍中的小朋友從頭到尾 說出自己的名字、信息:

(輸出節點存儲的信息):

code:

void CoutList(LinkList *L) {LinkList *p = L->next; //從 有效節點開始while (p != NULL){printf("%d", p->data); //小朋友喊出自己的信息p = p->next; //換下一個小朋友} }



由于小韋只能數到10,造成隊伍中的星星的嘲笑,并給他 起了個外號:小白。站在隊伍頭部的小韋很是氣憤,氣憤中的小韋突然就知道怎么數10以后的數字了。于是他查了一下嘲笑他的小朋友的位置,給他起外號報復:

修改某個節點的數據信息 :

code:

bool ChangeInfo(LinkList *&L, int i, int &e) //小韋查到了星星的位置,想好了外號 {int j = 0;LinkList *p = L;while (j < i && p != NULL) //如果是不在數據范圍內,說明小韋的數學真的很菜{j++;p = p->next;}if (p == NULL)return false;else{p->data = e; //如果找到了i位置上的星星,小韋就把他想好的外號賦予星星return true;} }



由于小韋的行為,使得某個位置上的樂樂表現的很氣憤。于是小韋查了樂樂的位置,并行使了隊長權利將其踢出了隊伍(因為 小韋知道樂樂未來會是一位IT大神,要讓樂樂掛掉先)。

刪除某個節點:

bool ListDelete(LinkList *&L, int i) //找到樂樂的位置 {int j = 0;LinkList *p = L, *q;while (j < i - 1 && p != NULL) {j++;p = p->next;}if (p == NULL) //如果找錯了,不存在i節點,說明小韋的 數學是體育老師教的,return false;else{q = p->next; //如果找到了樂樂,把樂樂一覺踹出隊伍,再讓樂樂前面的小朋友的手拉著樂樂后面 的小朋友的衣服if (q == NULL){return false;}p->next = q->next; free(q);return true;} }



雜七雜八的事情終于弄完了,于是 小韋也歸隊。(因為他 不想再單獨被沖走了)

插入數據元素:

code:

bool ListInsert(LinkList *&L, int i, int e) //小韋在某個位置上插入隊伍 {int j = 0;LinkList *p = L, *s;while (j < i - 1 && p != NULL){j++;p = p->next;}if (p == NULL)return false;else{s = (LinkList *)malloc(sizeof(LinkList));s->data = e;s->next = p->next;p->next = s;return true;} }
那么 現在開始過河了,由于河水 ?突然猛漲,小韋學長竟然又被沖走了。小伙伴們需要抓的更緊點,于是它們退回來重新 建隊。并將抓衣服的方式 更改了一下:讓前一個小朋友的手抓住后一個小朋友的衣服,后一個小朋友的手抓住他前面的小朋友的衣服。即(雙鏈表)

相應的此時建雙鏈表的方法也有兩種,與建立單鏈表過程相似,只需要加一個前驅結點即可:

code:

typedef struct Lnode {int data;struct Lnode *prior; //前驅節點struct Lnode *next; //后繼節點 }LinkList;

第一種建立方式頭插法(與單鏈表頭插法相似):

code:

void CreateList_F(LinkList *&L, int a[], int n) {LinkList *s;int i;L = (LinkList*)malloc(sizeof(LinkList));L->prior = L->next = NULL;for (i = 0; i < n; i++){s = (LinkList *)malloc(sizeof(LinkList));s->data = a[i];s->next = L->next;if (L->next != NULL){L->next->prior = s;}L->next = s;s->prior = L;} }



尾插法建立 雙鏈表:

code:

void CreatList_R(LinkList *&L, int a[], int n) {int i;LinkList *s, *r;r = L;for (i = 0; i < n; i++){s = (LinkList*)malloc(sizeof(LinkList));s->data = a[i];r->next = s;s->prior = r;}r->next = L->next; }


經過好多坎坷,終于到達的河的對岸,于是小伙伴們 手拉手圍成一個圈,興高采烈的哭了起來。

循環鏈表:

循環鏈表 只是將鏈表 的尾部節點的 next指向了鏈表 的開頭L;

下面我總結下代碼:


單鏈表:

typedef struct Lnode //數據節點 {int data;struct Lnode *next; }LinkList;void InitList(LinkList *&L) //創建空的單鏈表 {L = (LinkList *)malloc(sizeof(LinkList));L->next = NULL; }void CreateListH(LinkList *&L, int a[], int n) //頭插法建立單鏈表 {LinkList *s; int i;L = (LinkList *)malloc(sizeof(LinkList)); L是 鏈表的頭L->next = NULL; for (i = 0; i < n; i++) //將數據插入鏈表頭(L)的后面{s = (LinkList *)malloc(sizeof(LinkList));s->data = a[i];s->next = L->next; //即:s指向 L的 指向,L指向s;L->next = s;} }void CreateListR(LinkList *&L, int a[], int n) //尾插法建立單鏈表 {int i;LinkList *s, *r;L = (LinkList *)malloc(sizeof(LinkList)); //申請空間。開始時L雖然是表頭 ,同時也是尾r = L;for (i = 0; i < n; i++) // //將下一個 數據插入隊尾的后面,再讓該數據成為新的隊尾{s = (LinkList *)malloc(sizeof(LinkList));s->data = a[i];r->next = s; //r就是隊尾部,將 s插入r的后面,r = s; //插入后,那么s在最后的位置,讓其成為標記?,F在s就是新的隊尾}r->next = L->next; //隊伍建立完成后,最后 隊尾節點為 NULL; } </pre><pre code_snippet_id="1630697" snippet_file_name="blog_20160331_15_6131477" name="code" class="cpp"> int ListLength(LinkList *L) //返回單鏈表的長度 {int ans = 0;LinkList *p = L; //(要注意是LinkList * p = L)while (p->next != NULL) //如果 下一個節點不為空,肯定是有數據存儲的,于是ans++;{ans++;p = p->next;}return ans; }void CoutList(LinkList *L) //輸出每個節點的信息 {LinkList *p = L->next; //從頭開始(要注意是LinkList *p = L->next)while (p != NULL) //如果當前節點不為空,則 輸出信息{printf("%d", p->data);p = p->next;} }bool GetElem(LinkList *&L, int i, int &e) //修改某個位置上的數據信息 {int j = 0;LinkList *p = L;while (j < i && p != NULL) //如果沒有遍歷到i-1并且鏈表沒有結束{j++; //接著找p = p->next;}if (p == NULL) //如果結束時是因為鏈表結束了,則說明 i超出了范圍return false;else //否則,修改信息{p->data = e;return true;} }bool ListDelete(LinkList *&L, int i) //刪除某個節點 {int j = 0;LinkList *p = L, *q;while (j < i - 1 && p != NULL){j++;p = p->next;}if (p == NULL)return false;else //如果找到了該節點,{q = p->next; //那么讓當前節點的后記節點指向它后面 的后面,就相當于把 這個節點隔出來了if (q == NULL){return false;}p->next = q->next;free(q);return true;} }bool ListInsert(LinkList *&L, int i, int e) // 插入節點 {int j = 0;LinkList *p = L, *s;while (j < i - 1 && p != NULL){j++;p = p->next;}if (p == NULL)return false;else //如果 找到位置,先讓要插入的s節點指向當前節點的后繼,并讓當前節點的后繼指向s。{s = (LinkList *)malloc(sizeof(LinkList));s->data = e;s->next = p->next;p->next = s;return true;} }



雙鏈表:


typedef struct Lnode //雙鏈表節點 {int data;struct Lnode *prior;struct Lnode *next; }LinkList;void CreateList_F(LinkList *&L, int a[], int n) //頭插法建立雙鏈表 {LinkList *s;int i;L = (LinkList*)malloc(sizeof(LinkList));L->prior = L->next = NULL; //首先頭部節點的next 和prior為空for (i = 0; i < n; i++){s = (LinkList *)malloc(sizeof(LinkList)); s->data = a[i];s->next = L->next;if (L->next != NULL) //如果頭部節點的next不為空,那么L的下個節點的prior必須要指向s{L->next->prior = s;}L->next = s; //L的 next指向 s,s的 前驅節點指向L。s->prior = L;} }void CreatList_R(LinkList *&L, int a[], int n) 尾插法建立雙鏈表 {int i;LinkList *s, *r;r = L;for (i = 0; i < n; i++){s = (LinkList*)malloc(sizeof(LinkList)); //只需要 讓新加入的節點 的前驅節點指向當時隊尾即可,不用 考慮頭部L,因為是 尾插法。s->data = a[i];r->next = s;s->prior = r;}r->next = L->next; }

循環鏈表 ?的就不寫了,因為只需要 讓尾節點和頭結點關聯上就行了,不過要注意雙鏈表循環和單鏈表循環是有一定區別的。但是本質不變。

希望 ?這篇文章 可以 幫助你更好的理解或者復習鏈表操作?。

如有錯,請留言。

總結

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

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