C語言學(xué)習(xí)之鏈表的實(shí)現(xiàn)詳解
一、鏈表的概念
鏈表是一種物理存儲(chǔ)結(jié)構(gòu)上非連續(xù)、非順序的存儲(chǔ)結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接次序?qū)崿F(xiàn)的
二、鏈表的結(jié)構(gòu)
(1)單鏈表
(2)帶頭結(jié)點(diǎn)的單鏈表
(3)雙向鏈表
(4)循環(huán)單鏈表
(5)雙向循環(huán)鏈表
注釋:
(1)無頭單向非循環(huán)鏈表:結(jié)構(gòu)簡(jiǎn)單,一般不會(huì)單獨(dú)用來存數(shù)據(jù)。實(shí)際中更多是作為其他數(shù)據(jù)結(jié)構(gòu)的子結(jié)構(gòu),如哈希桶、圖的鄰接表等等。
(2)帶頭雙向循環(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ì)帶來很多優(yōu)勢(shì),實(shí)現(xiàn)反而簡(jiǎn)單了。
三、順序表和鏈表的區(qū)別和聯(lián)系
(1)順序表:
優(yōu)點(diǎn): 空間連續(xù),支持隨機(jī)訪問。
缺點(diǎn): 中間或前面部分的插入刪除時(shí)間復(fù)雜度為O(n),并且增容代價(jià)比較大。
(2)鏈表
優(yōu)點(diǎn): 任意位置插入刪除時(shí)間復(fù)雜度為O(1) 2.沒有增容問題,插入一個(gè)開辟一個(gè)空間。
缺點(diǎn): 以節(jié)點(diǎn)為單位存儲(chǔ),不支持隨機(jī)訪問。
四、鏈表的實(shí)現(xiàn)
(1)單鏈表的增刪查找等操作
#pragma once #include"common.h" typedef struct SListNode { ElemType data; struct SListNode* next; }SListNode; typedef struct SList { SListNode* head; }SList; /// /// //單鏈表的函數(shù)接口聲明 void SListInit(SList* plist); static SListNode* _Buynode(ElemType x); void SListPushBack(SList* plist, ElemType item);//1 void SListPushFront(SList* plist, ElemType item);//2 void SListShow(SList* plist);//3 void SListPopBack(SList* plist);//4 void SListPopFront(SList* plist);//5 void SListInsertVal(SList* plist, ElemType val);//7 void SqListDeleteByVal(SList* plist, ElemType val);//9 SListNode* SListFind(SList* plist, ElemType key);//10 size_t SListLength(SList* plist);//11 void SListSort(SList* plist);//13 void SListReverse(SList* plist);//14 void SListClear(SList* plist);//15 void SListDestroy(SList* plist); /// /// //單鏈表的函數(shù)接口實(shí)現(xiàn) void SListInit(SList* plist) { plist->head = NULL; } static SListNode* _Buynode(ElemType x) { SListNode* s = (SListNode*)malloc(sizeof(SListNode)); assert(s != NULL); s->data = x; s->next = NULL; return s; } //1 void SListPushBack(SList* plist, ElemType item) { assert(plist != NULL); SListNode* s = _Buynode(item); //插入的節(jié)點(diǎn)為第一個(gè)節(jié)點(diǎn) if (plist->head == NULL) { plist->head = s; return; } //O(n) SListNode* p = plist->head; //查找鏈表的尾部節(jié)點(diǎn) while (p->next != NULL) { p = p->next; } p->next = s; } //2 void SListPushFront(SList* plist, ElemType item) { assert(plist != NULL); SListNode* s = _Buynode(item); s->next = plist->head; plist->head = s; } //3 void SListShow(SList* plist) { assert(plist != NULL); SListNode* p = plist->head; while (p != NULL) { printf("%d-->", p->data); p = p->next; } printf("Over.\n"); } //4 void SListPopBack(SList* plist) { assert(plist != NULL); SListNode* p = plist->head; if (plist->head == NULL) { printf("單鏈表為空,輸出失敗!\n"); return; } if (p->next == NULL) { plist->head = NULL; return; } SListNode* prev = NULL; while (p->next != NULL) { prev = p; p = p->next; } prev->next = NULL; free(p); } //5 void SListPopFront(SList* plist) { assert(plist != NULL); SListNode* p = plist->head; if (plist->head == NULL) { printf("單鏈表為空,輸出失敗!\n"); return; } plist->head = p->next; free(p); } //6 //7 void SListInsertVal(SList* plist, ElemType val) { assert(plist != NULL); SListNode* prev = NULL; SListNode* p = plist->head; SListNode* s = _Buynode(val); while (p != NULL && val > p->data) { prev = p; p = p->next; } if (prev == NULL) { s->next = p; plist->head = s; } else { s->next = prev->next; prev->next = s; } } //10 SListNode* SListFind(SList* plist, ElemType key) { assert(plist != NULL); SListNode* p = plist->head; while (p != NULL && p->data != key) p = p->next; return p; } //9 void SqListDeleteByVal(SList* plist, ElemType val) { assert(plist != NULL); SListNode* prev = NULL; SListNode* p = SListFind(plist, val); if (p == NULL) { printf("要?jiǎng)h除的節(jié)點(diǎn)不存在.\n"); return; } if (p == plist->head) plist->head = p->next; else { prev = plist->head; while (prev->next != p) prev = prev->next; //刪除 prev->next = p->next; } free(p); } //11 size_t SListLength(SList* plist) { assert(plist != NULL); size_t len = 0; SListNode* p = plist->head; while (p != NULL) { len++; p = p->next; } return len; } //13 void SListSort(SList* plist) { assert(plist != NULL); SListNode* p = plist->head->next; SListNode* q, * t, * prev = NULL; plist->head->next = NULL; //斷開鏈表 t = plist->head; while (p != NULL) { q = p->next; while (t != NULL && p->data > t->data) { prev = t; t = t->next; } if (prev == NULL) { p->next = plist->head; plist->head = p; } else //if(prev->next!=NULL) { p->next = prev->next; prev->next = p; } p = q; t = plist->head; } } //14 void SListReverse(SList* plist) { assert(plist != NULL); SListNode* p = plist->head->next; SListNode* q; if (p->next == NULL) return; //斷開第一個(gè)節(jié)點(diǎn) plist->head->next = NULL; while (p != NULL) { q = p->next; p->next = plist->head; plist->head = p; p = q; } } //15 void SListClear(SList* plist) { assert(plist != NULL); SListNode* p = plist->head; while (p != NULL) { plist->head = p->next; free(p); p = plist->head; } } void SListDestroy(SList* plist) { SListClear(plist); plist->head = NULL; } ```c
(2)帶頭的雙循環(huán)鏈表的實(shí)現(xiàn)
#pragma once #include"common.h" / //帶頭的雙循環(huán)鏈表 typedef struct DCListNode { ElemType data; struct DCListNode* next; struct DCListNode* prev; }DCListNode; typedef struct DCList { DCListNode* head; }DCList; static DCListNode* _Buydnode(ElemType x); void DCListInit(DCList* plist); void DCListDestroy(DCList* plist); void DCListPushBack(DCList* plist, ElemType x);//1 void DCListPushFront(DCList* plist, ElemType x);//2 void DCListShow(DCList* plist);//3 void DCListPopBack(DCList* plist);//4 void DCListPopFront(DCList* plist);//5 void DCListInsertByVal(DCList* plist, ElemType val);//7 void DCListDeleteByVal(DCList* plist, ElemType val);//9 size_t DCListLength(DCList* plist);//11 void DCListSort(DCList* plist);//13 void DCListReverse(DCList* plist);//14 void DCListClear(DCList* plist);//15 DCListNode* DCListFind(DCList* plist, ElemType key);//10 static DCListNode* _Buydnode(ElemType x) { DCListNode* s = (DCListNode*)malloc(sizeof(DCListNode)); assert(s != NULL); s->data = x; s->next = s->prev = s; return s; } void DCListInit(DCList* plist) { plist->head = _Buydnode(0); } //1 void DCListPushBack(DCList* plist, ElemType x) { assert(plist != NULL); DCListNode* s = _Buydnode(x); s->prev = plist->head->prev; s->prev->next = s; s->next = plist->head; plist->head->prev = s; } //2 void DCListPushFront(DCList* plist, ElemType x) { assert(plist != NULL); DCListNode* s = _Buydnode(x); s->next = plist->head->next; s->next->prev = s; plist->head->next = s; s->prev = plist->head; } //3 void DCListShow(DCList* plist) { assert(plist != NULL); DCListNode* p = plist->head->next; while (p != plist->head) { printf("%d->", p->data); p = p->next; } printf("Over.\n"); } //4 void DCListPopBack(DCList* plist) { assert(plist != NULL); DCListNode* p = plist->head->prev; if (plist->head->next == plist->head) //if(p == plist->head) { printf("循環(huán)雙鏈表只有頭結(jié)點(diǎn),操作失敗.\n"); return; } plist->head->prev = p->prev; p->prev->next = plist->head; free(p); } //5 void DCListPopFront(DCList* plist) { assert(plist != NULL); DCListNode* p = plist->head->next; if (p == plist->head) { printf("循環(huán)雙鏈表只有頭結(jié)點(diǎn),操作失敗.\n"); return; } plist->head->next = p->next; p->next->prev = plist->head; free(p); } //7 void DCListInsertByVal(DCList* plist, ElemType val) { assert(plist != NULL); DCListNode* p = plist->head->next; while (p != plist->head && p->data < val) { p = p->next; } DCListNode* s = _Buydnode(val); s->next = p; s->prev = p->prev; p->prev->next = s; p->prev = s; } //9 void DCListDeleteByVal(DCList* plist, ElemType val) { assert(plist != NULL); DCListNode* p = DCListFind(plist, val); if (p == NULL) return; p->next->prev = p->prev; p->prev->next = p->next; free(p); } //10 DCListNode* DCListFind(DCList* plist, ElemType key) { assert(plist != NULL); DCListNode* p = plist->head->next; if (p == plist->head) { printf("雙循環(huán)鏈表只有頭結(jié)點(diǎn),查找失敗.\n"); return 0; } while (p != plist->head && p->data != key) { p = p->next; } if (p != plist->head) return p; return NULL; } //11 size_t DCListLength(DCList* plist) { assert(plist != NULL); size_t len = 0; DCListNode* p = plist->head->next; while (p != plist->head) { len++; p = p->next; } return len; } //13 void DCListSort(DCList* plist) { assert(plist != NULL); DCListNode* p = plist->head->next; DCListNode* q = p->next; //斷開鏈表 p->next = plist->head; plist->head->prev = p; while (q != plist->head) { p = q; q = q->next; //尋找p插入的位置 DCListNode* t = plist->head->next; while (t != plist->head && t->data < p->data) t = t->next; p->next = t; p->prev = t->prev; p->next->prev = p; p->prev->next = p; p = q; } } //14 void DCListReverse(DCList* plist) { assert(plist != NULL); DCListNode* p = plist->head->next; DCListNode* q = p->next; //斷開鏈表 p->next = plist->head; plist->head->prev = p; while (q != plist->head) { p = q; q = q->next; p->next = plist->head->next; p->prev = plist->head; p->next->prev = p; p->prev->next = p; //plist->head->next = p; } } //15 void DCListClear(DCList* plist) { assert(plist != NULL); DCListNode* p = plist->head->next; while (p != plist->head) { p->next->prev = p->prev; p->prev->next = p->next; free(p); p = plist->head->next; } } void DCListDestroy(DCList* plist) { DCListClear(plist); free(plist->head); plist->head = NULL; }
以上就是C語言學(xué)習(xí)之鏈表的實(shí)現(xiàn)詳解的詳細(xì)內(nèi)容,更多關(guān)于C語言鏈表的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語言使用ffmpeg實(shí)現(xiàn)單線程異步的視頻播放器
這篇文章主要為大家詳細(xì)介紹了C語言如何使用ffmpeg實(shí)現(xiàn)單線程異步的視頻播放器功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下2022-12-12C++設(shè)計(jì)模式之享元模式(Flyweight)
這篇文章主要為大家詳細(xì)介紹了C++設(shè)計(jì)模式之享元模式Flyweight,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04詳解C/C++ Linux出錯(cuò)處理函數(shù)(strerror與perror)的使用
我們知道,系統(tǒng)函數(shù)調(diào)用不能保證每次都成功,必須進(jìn)行出錯(cuò)處理,這樣一方面可以保證程序邏輯正常,另一方面可以迅速得到故障信息。本文主要為大家介紹兩個(gè)出錯(cuò)處理函數(shù)(strerror、perror)的使用,需要的可以參考一下2023-01-01基于C語言實(shí)現(xiàn)的TCP服務(wù)器的流程分析
本文詳細(xì)介紹了如何使用C語言編寫一個(gè)簡(jiǎn)單的TCP服務(wù)器,包括創(chuàng)建套接字、綁定IP和端口、監(jiān)聽連接請(qǐng)求、接受客戶端連接、數(shù)據(jù)接收與發(fā)送以及關(guān)閉套接字等步驟,最后通過一個(gè)簡(jiǎn)單的示例展示了TCP服務(wù)器的基本實(shí)現(xiàn)過程2024-10-10c 調(diào)用python出現(xiàn)異常的原因分析
本篇文章是對(duì)使用c語言調(diào)用python出現(xiàn)異常的原因進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05