<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          手?jǐn)]雙鏈表,圖解

          共 8664字,需瀏覽 18分鐘

           ·

          2021-03-27 12:21

          C語言,鏈表

          C++實(shí)現(xiàn)單向鏈表

          深入理解Linux內(nèi)核鏈表


          跟單鏈表不同,雙鏈表的節(jié)點(diǎn)包含兩個(gè)指針,一個(gè)指針指向上一個(gè)元素,一個(gè)指針指向下一個(gè)元素。


          如下圖






          學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)的時(shí)候,要像認(rèn)識(shí)一個(gè)人一樣,要了解這個(gè)人有什么特點(diǎn),比如喜歡打球,喜歡喝酒之類的。學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)也是一樣,要了解數(shù)據(jù)結(jié)構(gòu)的特點(diǎn)。


          我們要學(xué)習(xí)雙鏈表,需要搞明白鏈表這幾個(gè)特點(diǎn)


          1. 創(chuàng)建鏈表

          2. 往鏈表插入數(shù)據(jù)

          3. 刪除鏈表中的某個(gè)數(shù)據(jù)

          4. 刪除整個(gè)鏈表

          5. 查找鏈表

          6. 反轉(zhuǎn)鏈表



          先看看如何創(chuàng)建一個(gè)鏈表



          創(chuàng)建一個(gè)鏈表無非就是搞定鏈表頭,沒有頭的鏈表就是死鏈表,有頭就表示這個(gè)鏈表是存在的。當(dāng)然了,可能會(huì)存在循環(huán)鏈表,只有位置,沒有固定的頭指針。




          創(chuàng)建一個(gè)pHead,并且以后pHead頭指針保持不動(dòng),就表示我們創(chuàng)建好了一個(gè)鏈表頭指針。


          typedef struct Node{
              struct Node *prev;
              struct Node *next;
              int elements;
          }pNode;

          pNode * CreateHead(void)
          {
              pNode *head = NULL;
              head = (pNode *)malloc(sizeof(struct Node));
              head->next = NULL;
              head->prev = NULL;
              return head;
          }


          插入元素



          插入元素的方式有多種,可以頭插,可以尾插,也可以任意插,我只寫了簡(jiǎn)單的插入方式-尾插。



          int InsertElement(pNode *head,int element)
          {
              if(head == NULL)
              {
                  PRINTK_LINK("Head NULL\n");
                  return (-1);
              }

              pNode * pTemp = head;
              while(pTemp->next != NULL)
              {
                  pTemp = pTemp->next;
              }
              pNode * pElement = (pNode *)malloc(sizeof(struct Node));
              pElement->elements = element;
              pTemp->next = pElement;
              pElement->prev = pTemp;
              PRINTK_LINK("Element:%d\n",element);
              return (0);
          }


          遍歷一個(gè)鏈表



          遍歷鏈表是常規(guī)的操作,但是遍歷鏈表的方法有很多種,可以從頭開始遍歷,可以從尾部開始,在涉及二分查找的時(shí)候可以從中間某個(gè)位置開始遍歷。雖然方法很多,但是我只寫了一種方法,就是從頭開始遍歷鏈表,因?yàn)槭亲詈?jiǎn)單的。


          int TraverseLink(pNode *head)
          {
              if(head == NULL)
              {
                  PRINTK_LINK("Head NULL\n");
                  return (-1);
              }
              pNode * pTemp = head;

              while(pTemp->next != NULL)
              {
                  pTemp = pTemp->next;
                  PRINTK_LINK("Element:%d\n",pTemp->elements);
              }
              return (0);
          }


          刪除鏈表


          刪除整個(gè)鏈表是把鏈表的每個(gè)元素都刪除,并且把頭也刪除,并且把頭指針指向NULL。如果需要找到鏈表中的某個(gè)元素并刪除,就需要先找到鏈表中的元素,刪除掉,并且把前后的兩個(gè)元素連在一起。


          int DeleteLink(pNode *head)
          {
              if(head == NULL)
              {
                  PRINTK_LINK("Head NULL\n");
                  return (-1);
              }
              pNode * pTemp = head;
              while(pTemp->next != NULL)
              {
                  pTemp = pTemp->next;
              }

              while(pTemp != NULL)
              {
                  free(pTemp);
          pTemp = NULL;
                  pTemp = pTemp->prev;
              }
              return (0);
          }


          完整代碼


          #include "stdio.h"
          #include "string.h"
          #include "stdlib.h"

          #define LOG_TAG "[LINK]: %s() line: %d "
          #define PRINTK_LINK(fmt, args...)  printf(LOG_TAG fmt, __FUNCTION__, __LINE__,  ##args)

          typedef struct Node{
              struct Node *prev;
              struct Node *next;
              int elements;
          }pNode;

          pNode * CreateHead(void)
          {
              pNode *head = NULL;
              head = (pNode *)malloc(sizeof(struct Node));
              head->next = NULL;
              head->prev = NULL;
              return head;
          }

          int InsertElement(pNode *head,int element)
          {
              if(head == NULL)
              {
                  PRINTK_LINK("Head NULL\n");
                  return (-1);
              }

              pNode * pTemp = head;
              while(pTemp->next != NULL)
              {
                  pTemp = pTemp->next;
              }
              pNode * pElement = (pNode *)malloc(sizeof(struct Node));
              pElement->elements = element;
              pTemp->next = pElement;
              pElement->prev = pTemp;
              PRINTK_LINK("Element:%d\n",element);
              return (0);
          }

          int TraverseLink(pNode *head)
          {
              if(head == NULL)
              {
                  PRINTK_LINK("Head NULL\n");
                  return (-1);
              }
              pNode * pTemp = head;

              while(pTemp->next != NULL)
              {
                  pTemp = pTemp->next;
                  PRINTK_LINK("Element:%d\n",pTemp->elements);
              }
              return (0);
          }

          int DeleteLink(pNode *head)
          {
              if(head == NULL)
              {
                  PRINTK_LINK("Head NULL\n");
                  return (-1);
              }
              pNode * pTemp = head;
              while(pTemp->next != NULL)
              {
                  pTemp = pTemp->next;
              }

              while(pTemp != NULL)
              {
                  free(pTemp);
                  pTemp = pTemp->prev;
              }
              return (0);
          }


          int main()
          {
              pNode * pHead = CreateHead();
              InsertElement(pHead,13);
              InsertElement(pHead,8);
              InsertElement(pHead,0);
              InsertElement(pHead,4);
              InsertElement(pHead,485);
              InsertElement(pHead,94);

              TraverseLink(pHead);

              DeleteLink(pHead);
              return 0;
          }


          程序輸出


          ubuntu1804:~/c$ gcc shuanglianbiao.c && ./a.out
          [LINK]: InsertElement() line: 40 Element:13
          [LINK]: InsertElement() line: 40 Element:8
          [LINK]: InsertElement() line: 40 Element:0
          [LINK]: InsertElement() line: 40 Element:4
          [LINK]: InsertElement() line: 40 Element:485
          [LINK]: InsertElement() line: 40 Element:94
          [LINK]: TraverseLink() line: 56 Element:13
          [LINK]: TraverseLink() line: 56 Element:8
          [LINK]: TraverseLink() line: 56 Element:0
          [LINK]: TraverseLink() line: 56 Element:4
          [LINK]: TraverseLink() line: 56 Element:485
          [LINK]: TraverseLink() line: 56 Element:94


          總結(jié)

          我上面的代碼只設(shè)計(jì)了鏈表頭,如果設(shè)計(jì)鏈表尾部指針,應(yīng)用會(huì)更加靈活。


          相比于單鏈表,雙鏈表的操作會(huì)更加靈活,當(dāng)然,每一個(gè)節(jié)點(diǎn)都需要新增一個(gè)指向于上一個(gè)位置的指針。


          雙鏈表還可以把頭尾連接起來變成一個(gè)環(huán)形隊(duì)列。


          鏈表相對(duì)于數(shù)組來說,插入和刪除數(shù)據(jù)非???,因?yàn)椴恍枰苿?dòng)數(shù)據(jù),只需要改變指針的指向。


          雙鏈表內(nèi)存利用率高,如果是內(nèi)存緊張的硬件設(shè)備,使用鏈表操作可以節(jié)省內(nèi)存。相對(duì)于數(shù)組,鏈表可以做到按需分配內(nèi)存。


          鏈表是一種基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),建議做到自己能寫出一個(gè)鏈表,不要求十全十美,我曾經(jīng)面試遇到讓我手?jǐn)]一個(gè)棧。相對(duì)于那些C語言基礎(chǔ),寫代碼更能彰顯程序員的技術(shù)。






          推薦閱讀:
          專輯|Linux文章匯總
          專輯|程序人生
          專輯|C語言
          我的知識(shí)小密圈

          關(guān)注公眾號(hào),后臺(tái)回復(fù)「1024」獲取學(xué)習(xí)資料網(wǎng)盤鏈接。

          歡迎點(diǎn)贊,關(guān)注,轉(zhuǎn)發(fā),在看,您的每一次鼓勵(lì),我都將銘記于心~



          瀏覽 67
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美aaa日韩aaa国产 | 俺去也亚洲 | 青青草视频免费在线播放 | 囯产精品久久久久久久久久免费 | 久久肏屄 |