日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

链表的结构

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

文章目錄

  • 1.1 鏈表的概念及結構
    • 1.2 鏈表的分類
  • 1.3 鏈表的實現
  • 1.4 雙向鏈表的實現

1.1 鏈表的概念及結構

概念:鏈表是一種物理存儲結構上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的

  • 鏈表結構在邏輯上是連續的,但是在物理上不一定是連續的
  • 現實中的結點一般都是從堆上申請出來的
  • 從堆上申請的空間,是按照一定的策略來分配的,兩次申請的空間可能連續,也可能不連續
  • 假設在32位系統上,節點中 值位int類型,則一個節點的大小為8個字節,則也有可能有下述鏈表:

    1.2 鏈表的分類

    實際中鏈表的結構非常多樣,以下情況組合起來就有8種鏈表結構:

  • 單向或者雙向
  • 帶頭或者不帶頭
  • 循環或者非循環

  • 雖然有這么多的鏈表的結構,但是我們實際中最常用還是兩種結構 :

    無頭單向非循環鏈表

    帶頭雙向循環鏈表

  • 無頭單向非循環鏈表:結構簡單,一般不會單獨用來存數據。實際中更多是作為其他數據結構的子結構
  • 帶頭雙向循環鏈表:結構最復雜,一般用在單獨存儲數據。實際中使用的鏈表數據結構,都是帶頭雙向循環鏈表。另外這個結構雖然結構復雜,但是使用代碼實現以后會發現結構會帶來很多優勢,實現反而簡單了,后面我們代碼實現了就知道了。
  • 1.3 鏈表的實現

    sList.h:

    typedef int SLT;typedef struct SListNode {SLT data;struct SListNode* next; }s;//打印鏈表 void SListPrint(s* plist);// 動態申請一個節點 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:

    //創建新節點 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 雙向鏈表的實現

    List.h:

    typedef int tp;typedef struct Listnode {struct Listnode* prev;struct Listnode* next;tp data;}List; //創建新節點 List* BuyListNode(tp x); // 創建返回鏈表的頭結點. 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位置的節點

    List.c:

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

    看代碼即可知道

    //創建新節點 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;//原來的尾節點tail->next = newnode;//尾節點指向新的節點//新節點鏈接原來的尾節點和頭節點newnode->prev = tail;newnode->next = phead;//頭節點鏈接新節點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;//原來的首節點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位置的結點 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); }

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

    總結

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

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