雙向鏈表的基本操作

1.雙向鏈表的數據結構
typedef char DLinkType;typedef struct DLinkNode 
{ DLinkType data; struct DLinkNode* next; struct DLinkNode* prev; 
}DLinkNode; 

????雙向帶頭結點的鏈表有三個成員, 一個是數據, 一個是指針 next 指向當前結點的下一個結點, 一個指針 prev 指向當前結點的 前一個結點,即每一個節點都有一個直接的前驅, 一個直接的后繼, 這里只討論帶頭結點的雙向鏈表。

2.雙向鏈表的初始化
/*** 初始化雙鏈表**/void DLinkListInit(DLinkNode** phead)
{if(phead == NULL){return;//非法輸入}*phead = (DLinkNode*)malloc(sizeof(DLinkNode));(*phead) -> data = 0;(*phead) -> next = *phead;(*phead) -> prev = *phead;
}

????帶頭結點雙向鏈表的初始化即就是用一個傀儡節點代表其為空,這里將頭節點的數據初始化為 0, 注意,雙向鏈表中沒有空指針,所以將雙向鏈表的頭節點的 next 指向它自己, 將雙向鏈表的 prev 指向它自己,即判斷一個雙向帶頭節點的鏈表是否為空的條件就是head -> next == head 或者是 head -> prev == head。

3.創建一個新節點

????既然需要對鏈表進行插入數據, 那便需要對其創建一個指定數據的節點,然后將其插入到當前的鏈表中。創建一個節點就是對其先分配空間, 再將節點對應的數據改為需要的目標數據。

/*** 創建一個新節點**/
DLinkNode* DLinkNodeCreat(DLinkType value)
{DLinkNode* new_node = (DLinkNode*)malloc(sizeof(DLinkNode));if(new_node == NULL){return NULL;//內存分配失敗}new_node -> data = value;new_node -> next = new_node;new_node -> prev = new_node;return new_node;
}
4.頭插一個新結點

?&enap;?&enap;對雙向鏈表的頭插節點也就是先創建一個新結點,然后定義一個指針 prev 指向頭結點的下一個節點, 即prev = head -> next, 然后修改對應的 prev 和 所創建的新結點 new_node 的指向, 即 讓 prev -> next = new_node, 再讓new_node -> prev = prev,就OK了

/*** 頭插一個節點**/void DLinkListPushFront(DLinkNode* head, DLinkType value)
{if(head == NULL){return;//非法輸入}DLinkNode* new_node = DLinkNodeCreat(value);DLinkNode* prev = head;DLinkNode* next = head -> next;prev -> next = new_node;new_node -> prev = prev;new_node -> next = next;next -> prev = new_node;
}
5.頭刪一個節點

?????既然頭刪一個節點就必須先定義一個指針 to_delete 指向要刪除的節點, 即 head ->next, 然后在定義一個指針指向要刪除的元素的下一個節點, 即定義一個指針 next = to_delete -> next, 然后修改head和 next 指針的指向即可, 最后將 to_delete 所指向的節點銷毀即可。

/*** 頭刪一個節點**/
void DLinkListPopFront(DLinkNode* head)
{if(head == NULL){return;//非法輸入}if(head -> next == head){return;//空鏈表}DLinkNode* to_delete = head -> next;DLinkNode* next = to_delete -> next;head -> next = next;next -> prev = head;DLinkNodeDstroy(to_delete);
}/*** 銷毀一個節點**/void DLinkNodeDstroy(DLinkNode* to_delete)
{free(to_delete);to_delete = NULL;
}
6.尾插一個節點

????尾插一個節點和鏈表頭插一個元素道理基本相似, 即先創建一個節點 new_node, 然后在定義一個指針 prev = head -> prev,最后修改 head 和 new_node 指針的指向, 接下來再修改 new_node 和 next 指針的指向就可以了。即讓 head -> prev = new_node, new_node -> next = head, new_node -> prev = prev, prev -> next = new_node, 此時就已經將新的元素尾插到鏈表中了

/*** 尾插一個節點**/DLinkNode* DLinkListPushBack(DLinkNode* head, DLinkType value)
{if(head == NULL){return NULL;//非法輸入}DLinkNode* new_node = DLinkNodeCreat(value);DLinkNode* next = head -> next;new_node -> next = next;next -> prev = new_node;head -> next = new_node;new_node -> prev = head;return head;
}
7.尾刪一個節點

????往雙鏈表中尾插一個元素就是先找到最后一個節點, to_delete = head -> prev, 然后記下 to_delete 節點的前一個節點, 即 prev = to_delete -> prev, 然后讓 prev -> next = head, haed -> prev = prev, 再將to_delete 刪除就可以了

/*** 尾刪一個元素**/void DLinkListPopBack(DLinkNode* head)
{if(head == NULL){return;//非法輸入}if(head -> next == head){return;//刪除空鏈表}DLinkNode* to_delete = head -> prev;DLinkNode* prev = to_delete -> prev;head -> prev = prev;prev -> next = head;DLinkNodeDstroy(to_delete);
}
8.在雙向鏈表中查找值為 to_find 節點,并且返回該節點所對應的位置

?&esnp;??定義一個指針cur 指向 head -> next, 然后讓 cur 依次遍歷整個鏈表, 當 cur -> data == to_find 時,就將此時的 cur 返回即可


DLinkNode* DLinkListFind(DLinkNode* head, DLinkType to_find)
{if(head == NULL){return NULL;//非法輸入}if(head -> next == head){return NULL;}DLinkNode* cur = head -> next;for(; cur != head; cur = cur -> next){if(cur -> data == to_find){return cur;}}return NULL;//沒有找到
}
9.往對應位置 pos 處插入一個值為 value的新結點

????往指定位置插入一個值為value 的節點, 需要先創建一個新結點, 然后定義一個指針 prev = pos -> prev, 再定義一個指針 next = pos -> next, 然后改變 prev 和 新節點 之間指針的指向, 以及 新結點和next指針之間的指向就可以將其插入到指定位置 pos 處了

/*** 往 pos 所對應的位置處插入 value ***/void DLinkListInsert(DLinkNode* pos, DLinkType value)
{if(pos == NULL){return;//非法輸入}DLinkNode* new_node = DLinkNodeCreat(value);DLinkNode* prev = pos -> prev;//prev vs new_nodeprev -> next = new_node;new_node -> prev = prev;//new_node vs posnew_node -> next = pos;pos -> prev = new_node;
}
10.往指定位置之后插入一個值為 value 的結點

???? 先創建一個新結點 new_node,再定義一個指針 prev = pos, 接下來定義一個指針 next = pos -> next, 然后改變 new_node 節點和 prev 節點 之間的指向, 最后改變 new_node 和 next 之間節點指針指向就 OK 了

/*** 往指定位置之后插入一個元素**/void DLinkListInsertAfter(DLinkNode* pos, DLinkType value)
{if(pos == NULL){return;//非法輸入}DLinkNode* new_node = DLinkNodeCreat(value);DLinkNode* next = pos -> next;pos -> next = new_node;new_node -> prev = pos;new_node -> next = next;next -> prev = new_node;
}
11. 刪除某個元素對應的結點

????刪除某個元素對應的節點就先找到要刪除節點對應的位置, 然后再將這個位置對應的節點刪掉就可以了, 如果鏈表中沒有這個元素,或者鏈表是空鏈表則直接返回.

/*** 刪除某個元素對應的結點**/void DLinkListErase(DLinkNode* head, DLinkType to_delete)
{if(head == NULL){return;//非法輸入}if(head -> next == NULL){return;//刪除空鏈表}DLinkNode* cur = DLinkListFind(head, to_delete);if(cur == NULL){return;//刪除不存在的節點}DLinkNode* prev = cur -> prev;DLinkNode* next = cur -> next;prev -> next = next;next -> prev = prev;DLinkNodeDstroy(cur);
}
12.求鏈表長度
/*** 求鏈表長度**/size_t DLinkListSize(DLinkNode* head)
{DLinkNode* cur = head -> next;size_t size = 0;while(cur != head){cur = cur -> next;size++;}return size;
}
13. 鏈表判空
/*** 鏈表判空**/int DLinkListEmpty(DLinkNode* head)
{if(head == NULL){return -1;//非法輸入}if(head -> next == head){return 1;}return 0;
}
14.刪除鏈表中所有相同的結點

void DLinkListRemoveAll(DLinkNode* head, DLinkType to_delete)
{if(head == NULL){                                                                                                                                                    return;//非法輸入}if(head -> next == head){return;//空鏈表}DLinkNode* cur = head -> next;while(cur != head){if(to_delete == cur -> data){DLinkListErase(head, to_delete);}cur = cur -> next;}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384091.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384091.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384091.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

匿名管道

1.進程通信的目的 (1) 數據傳輸: 一個進程需要將它的數據傳輸給另一個進程 ????(2) 資源共享: 多個進程之間共享同樣的資源 ????(3) 通知事件: 一個進程需要向另一個或一組進程發送消息, 通知它們發生了什么事情 2.管道 管道是一種進程之間通信的一種方式, 我們把從…

Currency Exchange——最短路Bellman-Ford算法

【題目描述】 Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and performs exchange operations only with these currencies. There can be several points specializing in the sam…

C++實現String類

http://blog.csdn.net/randyjiawenjie/article/details/6709539 C實現String類,還沒有完成,待繼續。 有以下注意的點: (1)賦值操作符返回的是一個MyString&,而重載的返回的是一個MyString。其中的原因…

POJ 3370 Halloween treats——鴿巢原理+思維

【題目描述】 POJ 3370 Halloween treats Description Every year there is the same problem at Halloween: Each neighbour is only willing to give a certain total number of sweets on that day, no matter how many children call on him, so it may happen that a chi…

將信號量代碼生成靜態庫以及動態庫

1.信號量相關代碼生成靜態庫 2.信號量相關代碼生成動態庫

Wormholes——Bellman-Ford判斷負環

【題目描述】 While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of…

C++11 標準新特性:Defaulted 和 Deleted 函數

https://www.ibm.com/developerworks/cn/aix/library/1212_lufang_c11new/index.html Defaulted 函數 背景問題 C 的類有四類特殊成員函數,它們分別是:默認構造函數、析構函數、拷貝構造函數以及拷貝賦值運算符。這些類的特殊成員函數負責創建、初始化、…

順序表實現棧相關操作

1.棧的相關概念 棧是一種特殊的線性表, 其中只允許在固定的一端進行插入和刪除元素.進行數據插入和刪除的一端叫做棧頂, 另一端成為棧底. 不含任何元素的棧稱為空棧, 棧又稱為先進先出的線性表. 2. 順序棧的結構 3. 順序棧的具體操作 (1). 數據結構 typedef char SeqStackTyp…

MPI Maelstrom——Dijkstra

【題目描述】 BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distributed shared memory machine with a hierarchical communication subsystem. Valentine McKee’s research advisor, Jack Swigert, has asked her to bench…

雙向帶環帶頭結點的鏈表實現棧

1. 數據結構 利用帶頭結點帶環的結點實現棧的相關操作.因此, 每一個結點包括了一個前驅, 一個后繼, 還有一個數據成員 typedef char DLinkStackType;typedef struct DLinkStack {DLinkStackType data;struct DLinkStack* next;struct DLinkStack* prev; }DLinkStack;2. 初始化…

Cow Contest——Floyed+連通性判斷

【題目描述】 N (1 ≤ N ≤ 100) cows, conveniently numbered 1…N, are participating in a programming contest. As we all know, some cows code better than others. Each cow has a certain constant skill rating that is unique among the competitors. The contest …

C++11 標準新特性:委派構造函數

https://www.ibm.com/developerworks/cn/rational/1508_chenjing_c11/index.html陳 晶2015 年 8 月 11 日發布WeiboGoogle用電子郵件發送本頁面 1本文首先介紹了在委派構造函數提出之前類成員構造所面臨的問題,再結合實例介紹了委派構造函數的用法,并說明…

順序表實現隊列

一. 隊列相關概念 隊列是只允許在一段進行插入元素, 在另一端進行刪除元素的線性表,即只允許對隊列進行尾插,頭刪的操作.隊列具有先進先出, 后進后出的特性. ???????? 1.初始化 void SeqQueInit(SeqQue* q) {if(q NULL){return;//非法輸入}q -> head 0;q -> …

Arbitrage——判斷正環Bellman-Ford/SPFA

【題目描述】 Arbitrage is the use of discrepancies in currency exchange rates to transform one unit of a currency into more than one unit of the same currency. For example, suppose that 1 US Dollar buys 0.5 British pound, 1 British pound buys 10.0 French …

鏈表實現隊列

上篇博客是用順序表實現隊列, 現在用雙向帶頭結點帶環鏈表實現對隊列的出隊列, 入隊列, 取隊首元素, 以及銷毀隊列的相關操作 1.初始化鏈表 void DLinkQueInit(DLinkQue** q) {if(q NULL){return;//非法輸入}if(*q NULL){return;//非法輸入帶頭結點的鏈表至少有一個傀儡結點…

HDU - 1796——容斥原理+二進制枚舉

【題目描述】 Now you get a number N, and a M-integers set, you should find out how many integers which are small than N, that they can divided exactly by any integers in the set. For example, N12, and M-integer set is {2,3}, so there is another set {2,3,4,…

數據結構學習(二)——單鏈表的操作之頭插法和尾插法創建鏈表

http://blog.csdn.net/abclixu123/article/details/8210109 鏈表也是線性表的一種,與順序表不同的是,它在內存中不是連續存放的。在C語言中,鏈表是通過指針相關實現的。而單鏈表是鏈表的其中一種,關于單鏈表就是其節點中有數據域和…

信號的基本概念以及信號的產生

一. 信號產生的場景 1. 用戶輸入命令, 在shell 啟動一個前臺進程 ???? 2. 當用戶按一下 Ctrl C 的時候,從鍵盤產生一個硬件中斷 ???? 3. 此時CPU 正在執行這個進程的帶代碼, 則該進程的執行代碼暫停執行, CPU 從用戶態切換到內核態處理該硬件中斷. ???? 4. 中斷…

HDU - 1028——母函數入門

【題目描述】 “Well, it seems the first problem is too easy. I will let you know how foolish you are later.” feng5166 says. “The second problem is, given an positive integer N, we define an equation like this: Na[1]a[2]a[3]…a[m]; a[i]>0,1<m<N;…

信號的阻塞

一. 阻塞信號 1.信號的相關概念 ????(1) 遞達: 實際執行信號的處理動作稱為信號的遞達 ????(2) 未決: 信號從產生到遞達之間的過程叫做信號的未決 ????(3) 阻塞: 進程可以選擇阻塞某個信號, 被阻塞的信號產生時將保持在未決狀態, 直到進程解除該信號的屏蔽, 才…