作者:舊夢(mèng)拾遺186
專欄:數(shù)據(jù)結(jié)構(gòu)成長(zhǎng)日記
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-514000.html
前言:
帶頭雙向循環(huán)鏈表:結(jié)構(gòu)最復(fù)雜,一般用在單獨(dú)存儲(chǔ)數(shù)據(jù)。實(shí)際中使用的鏈表數(shù)據(jù)結(jié)構(gòu),都是帶頭雙向循環(huán)鏈表。另外這個(gè)結(jié)構(gòu)雖然結(jié)構(gòu)復(fù)雜,但是使用代碼實(shí)現(xiàn)以后會(huì)發(fā)現(xiàn)結(jié)構(gòu)會(huì)帶來(lái)很多優(yōu)勢(shì),實(shí)現(xiàn)反而簡(jiǎn)單了。
現(xiàn)在我們來(lái)通過(guò)代碼實(shí)現(xiàn)帶頭雙向循環(huán)鏈表,結(jié)構(gòu)上雖然是鏈表最復(fù)雜的,但是并沒(méi)有我們想象的那么困難,恰恰相反,其代碼實(shí)現(xiàn)比較簡(jiǎn)單
?
帶頭雙向鏈表樣例:
?
代碼實(shí)現(xiàn)?
List.h
#pragma once #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <stdbool.h> typedef int LTDataType; typedef struct ListNode { struct ListNode* next; struct ListNode* prev; LTDataType data; }LTNode; LTNode* ListInit(); void ListPrint(LTNode* phead); void ListPushBack(LTNode* phead, LTDataType x); void ListPushFront(LTNode* phead, LTDataType x); void ListPopBack(LTNode* phead); void ListPopFront(LTNode* phead); bool ListEmpty(LTNode*phead); size_t ListSize(LTNode*phead); LTNode* ListFind(LTNode* phead,LTDataType x); //在pos之前插入 void ListInsert(LTNode* pos, LTDataType x); //刪除pos位置 void ListErase(LTNode* pos); void ListDestory(LTNode* phead);
List.c?
#include "List.h" LTNode* ListInit() { LTNode* guard = (LTNode*)malloc(sizeof(LTNode)); if (guard == NULL) { perror("malloc fail"); exit(-1); } guard->next = guard; guard->prev = guard; return guard; } LTNode* BuyListNode(LTDataType x) { LTNode* node = (LTNode*)malloc(sizeof(LTNode)); if (node == NULL) { perror("malloc fail"); exit(-1); } node->next = NULL; node->prev = NULL; node->data = x; return node; } void ListPrint(LTNode* phead) { assert(phead); printf("phead<=>"); LTNode* cur = phead->next; while (cur != phead) { printf("%d<=>", cur->data); cur = cur->next; } printf("\n"); } void ListPushBack(LTNode* phead, LTDataType x) { assert(phead); LTNode* newnode = BuyListNode(x); LTNode* tail = phead->prev; tail->next = newnode; newnode->prev = tail; newnode->next = phead; phead->prev = newnode; } void ListPushFront(LTNode* phead, LTDataType x) { assert(phead); LTNode* newnode = BuyListNode(x); //考慮先后順序 /*newnode->next = phead->next; phead->next->prev = newnode; phead->next = newnode; newnode->prev = phead;*/ //記錄下一位,就不用考慮順序 LTNode* first = phead->next; phead->next = newnode; newnode->prev = phead; newnode->next = first; first->prev = newnode; } void ListPopBack(LTNode* phead) { assert(phead); assert(!ListEmpty(phead)); LTNode* tail = phead->prev; LTNode* prev = tail->prev; prev->next = phead; phead->prev = prev; free(tail); tail = NULL; } void ListPopFront(LTNode* phead) { assert(phead); assert(!ListEmpty(phead)); LTNode* first = phead->next; LTNode* second = first->next; phead->next = second; second->prev = phead; free(first); first = NULL; } bool ListEmpty(LTNode* phead) { assert(phead); return phead->next == phead; } size_t ListSize(LTNode*phead) { assert(phead); size_t n = 0; LTNode* cur = phead->next; while (cur != phead) { ++n; cur = cur->next; } return n; } LTNode* ListFind(LTNode* phead, int x) { assert(phead); size_t n = 0; LTNode* cur = phead->next; while (cur != phead) { if (cur->data == x) { return cur; } } return NULL; } //在pos之前插入 void ListInsert(LTNode* pos, LTDataType x) { assert(pos); LTNode* prev = pos->prev; LTNode* newnode = BuyListNode(x); prev->next = newnode; newnode->prev = prev; newnode->next = pos; pos->prev = newnode; } //刪除pos位置 void ListErase(LTNode* pos) { assert(pos); LTNode* prev = pos->prev; LTNode* next = pos->next; prev->next = next; next->prev = prev; free(pos); } //可以傳二級(jí),內(nèi)部置空 //一級(jí)指針外部置空 void ListDestory(LTNode* phead) { assert(phead); LTNode* cur = phead->next; while (cur != phead) { LTNode* next = cur->next; free(cur); cur = next; } free(phead); }
?test.c
#include "List.h" //測(cè)試尾插、頭插、尾刪、打印 void TestList1() { LTNode* plist = ListInit(); ListPushBack(plist, 1); ListPushBack(plist, 2); ListPushBack(plist, 3); ListPushBack(plist, 4); ListPrint(plist); ListPushFront(plist, 10); ListPushFront(plist, 20); ListPushFront(plist, 30); ListPushFront(plist, 40); ListPrint(plist); ListPopBack(plist); ListPopBack(plist); ListPopBack(plist); ListPopBack(plist); ListPrint(plist); ListPopBack(plist); ListPopBack(plist); ListPopBack(plist); ListPopBack(plist); ListPrint(plist); ListPopBack(plist); ListPrint(plist); } //測(cè)試頭刪、銷毀 void TestList2() { LTNode* plist = ListInit(); ListPushBack(plist, 1); ListPushBack(plist, 2); ListPushBack(plist, 3); ListPushBack(plist, 4); ListPrint(plist); ListPopFront(plist); ListPopFront(plist); ListPrint(plist); ListPopFront(plist); ListPopFront(plist); ListPrint(plist); ListDestory(plist); plist = NULL; } int main() { //TestList1(); TestList2(); return 0; }
總結(jié):
?
?
?
?
結(jié)語(yǔ):
?鏈表的學(xué)習(xí)結(jié)束啦?。。⊥瑢W(xué)們要時(shí)常復(fù)習(xí)和刷題啊,我也寫(xiě)了好多鏈表的習(xí)題博客,同學(xué)們可以來(lái)訪問(wèn)啦。
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-514000.html
?
到了這里,關(guān)于【數(shù)據(jù)結(jié)構(gòu)與算法】雙向鏈表的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!