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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

链表的结构

發(fā)布時間:2023/12/31 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 链表的结构 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 1.1 鏈表的概念及結(jié)構(gòu)
    • 1.2 鏈表的分類
  • 1.3 鏈表的實現(xiàn)
  • 1.4 雙向鏈表的實現(xiàn)

1.1 鏈表的概念及結(jié)構(gòu)

概念:鏈表是一種物理存儲結(jié)構(gòu)上非連續(xù)、非順序的存儲結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接次序?qū)崿F(xiàn)的

  • 鏈表結(jié)構(gòu)在邏輯上是連續(xù)的,但是在物理上不一定是連續(xù)的
  • 現(xiàn)實中的結(jié)點一般都是從堆上申請出來的
  • 從堆上申請的空間,是按照一定的策略來分配的,兩次申請的空間可能連續(xù),也可能不連續(xù)
  • 假設(shè)在32位系統(tǒng)上,節(jié)點中 值位int類型,則一個節(jié)點的大小為8個字節(jié),則也有可能有下述鏈表:

    1.2 鏈表的分類

    實際中鏈表的結(jié)構(gòu)非常多樣,以下情況組合起來就有8種鏈表結(jié)構(gòu):

  • 單向或者雙向
  • 帶頭或者不帶頭
  • 循環(huán)或者非循環(huán)

  • 雖然有這么多的鏈表的結(jié)構(gòu),但是我們實際中最常用還是兩種結(jié)構(gòu) :

    無頭單向非循環(huán)鏈表

    帶頭雙向循環(huán)鏈表

  • 無頭單向非循環(huán)鏈表:結(jié)構(gòu)簡單,一般不會單獨用來存數(shù)據(jù)。實際中更多是作為其他數(shù)據(jù)結(jié)構(gòu)的子結(jié)構(gòu)
  • 帶頭雙向循環(huán)鏈表:結(jié)構(gòu)最復雜,一般用在單獨存儲數(shù)據(jù)。實際中使用的鏈表數(shù)據(jù)結(jié)構(gòu),都是帶頭雙向循環(huán)鏈表。另外這個結(jié)構(gòu)雖然結(jié)構(gòu)復雜,但是使用代碼實現(xiàn)以后會發(fā)現(xiàn)結(jié)構(gòu)會帶來很多優(yōu)勢,實現(xiàn)反而簡單了,后面我們代碼實現(xiàn)了就知道了。
  • 1.3 鏈表的實現(xiàn)

    sList.h:

    typedef int SLT;typedef struct SListNode {SLT data;struct SListNode* next; }s;//打印鏈表 void SListPrint(s* plist);// 動態(tài)申請一個節(jié)點 s* BuySListNode(SLT x);//單鏈表尾插 void SListPushBack(s** pplist, SLT x);//單鏈表頭插 void SListPushFront(s** pplist, SLT x);//單鏈表尾刪 void SListPopBack(s** pplist);//單鏈表頭刪 void SListPopFront(s** pplist);

    sList.c:

    //創(chuàng)建新節(jié)點 s* BuySListNode(SLT x) {s* NewNode = (s*)malloc(sizeof(s));NewNode->data = x;NewNode->next = NULL;return NewNode; }//打印鏈表 void SListPrint(s *plist) {assert(plist);s* tail = plist;while (tail != NULL){printf("%d ", tail->data);tail = tail->next;}printf("\n");}//尾插 void SListPushBack(s** pplist, SLT x) {s *new = BuySListNode(x);if (*pplist == NULL){*pplist = new;}else{s* tail = *pplist;while (tail->next != NULL){tail = tail->next;}tail->next = new;} }//頭插 void SListPushFront(s** pplist, SLT x) {s *NewNode = BuySListNode(x);NewNode->next = *pplist;*pplist = NewNode;}//尾刪 void SListPopBack(s** pplist) {assert(*pplist);if ((*pplist)->next == NULL){free(*pplist);*pplist = NULL;}else{s* tail = *pplist;s* prev = NULL;while (tail->next != NULL){prev = tail;tail = tail->next;}free(tail);tail = NULL;prev->next = NULL;} }//頭刪 void SListPopFront(s** pplist) {assert(*pplist);s* tmp = *pplist;*pplist = (*pplist)->next;free(tmp);tmp = NULL;

    1.4 雙向鏈表的實現(xiàn)

    List.h:

    typedef int tp;typedef struct Listnode {struct Listnode* prev;struct Listnode* next;tp data;}List; //創(chuàng)建新節(jié)點 List* BuyListNode(tp x); // 創(chuàng)建返回鏈表的頭結(jié)點. List* ListInit(void); // 雙向鏈表打印 void ListPrint(List* phead); // 雙向鏈表尾插 void ListPushBack(List* phead, tp x); // 雙向鏈表尾刪 void ListPopBack(List* phead); // 雙向鏈表頭插 void ListPushFront(List* phead, tp x); // 雙向鏈表頭刪 void ListPopFront(List* phead); // 雙向鏈表查找 List* ListSearch(List* phead, tp x); // 雙向鏈表在pos的前面進行插入 List* ListInsert(List*phead, tp y, tp x); // 雙向鏈表刪除pos位置的節(jié)點

    List.c:

    對于帶頭雙向循環(huán)鏈表,中間插入適用于頭插與尾插,中間刪除適用于頭刪與尾刪

    看代碼即可知道

    //創(chuàng)建新節(jié)點 List* BuyListNode(tp x) {List* newnode = (List*)malloc(sizeof(List));newnode->data = x;return newnode;}//初始化鏈表 List* ListInit(void) {List* phead = BuyListNode(0);phead->next = phead;phead->prev = phead; }//尾插 void ListPushBack(List* phead, tp x) {assert(phead != NULL);List* newnode = BuyListNode(x);List* tail = phead->prev;//原來的尾節(jié)點tail->next = newnode;//尾節(jié)點指向新的節(jié)點//新節(jié)點鏈接原來的尾節(jié)點和頭節(jié)點newnode->prev = tail;newnode->next = phead;//頭節(jié)點鏈接新節(jié)點phead->prev = newnode; }//打印鏈表 void ListPrint(List* phead) {assert(phead != NULL);assert(phead->next != phead);List* cur = phead->next;while (cur != phead){printf("%d ", cur->data);cur = cur->next;}printf("\n");}//頭插 void ListPushFront(List* phead, tp x) {assert(phead != NULL);List* newnode = BuyListNode(x);List* first = phead->next;//原來的首節(jié)點phead->next = newnode;newnode->prev = phead;newnode->next = first;first->prev = newnode;}//尾刪 void ListPopBack(List* phead) {assert(phead != NULL);assert(phead->next != phead);ListErase(phead,phead->prev->data); }//頭刪 void ListPopFront(List* phead) {assert(phead != NULL);assert(phead->next != phead);ListErase(phead, phead->next->data); }//暫時只考慮找到的情況 List* ListSearch(List* phead, tp x) {assert(phead != NULL);assert(phead->next != phead);List* cur = phead->next;List* pos = NULL;while (cur != phead){if (cur->data == x){pos = cur;return pos;}cur = cur->next;} }//插在pos之前 List* ListInsert(List*phead, tp y, tp x) {List* pos = ListSearch(phead, y);List* newnode = BuyListNode(x);List* posfront = pos->prev;posfront->next = newnode;newnode->prev = posfront;newnode->next = pos;pos->prev = newnode; }//刪除pos位置的結(jié)點 void ListErase(List* phead, tp y) {assert(phead != NULL);List* pos = ListSearch(phead, y);(pos->prev)->next = (pos->next);(pos->next)->prev = pos->prev;free(pos); }

    關(guān)于鏈表的一些題目,可以關(guān)注作者的下一篇博客一些鏈表OJ題
    光講概念畢竟是枯燥的,做更多的題目我們才能加深對鏈表的理解

    總結(jié)

    以上是生活随笔為你收集整理的链表的结构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。