資料結構:雙向連結串列

gaopengtttt發表於2016-09-18
原創:轉載請註明
在前面介紹了單項鍊表,
http://blog.itpub.net/7728585/viewspace-2125007/
在實際的應用中雙向連結串列應用也是非常多的,因為我本生是一名DBA,我知道的在資料庫中雙向連結串列應用非常廣泛,在雙向連結串列中
我們多了一個*prior 指向前一個節點,那麼這樣如果我們已知一個節點的指標要求得上一個節點的指標就變得非常簡單了,
時間複雜度由O(n)下降到一個常數O(1),關於這個實現函式我覺得沒必要寫了太簡單了。我準備實現如下一些函式及功能
bool makenode(int datavalue,DULNODEP* p); //makenode next and prior is NULL
void freenode(DULNODEP p); //freenode
bool initlist(LISTHEADP* p); //initlist with no node head last current pointor is NULL
void destroylist(LISTHEADP p); //destroy a list,every list thing is not live
void clearlist(LISTHEADP p);//clear a list,but head is live and head last current pointor is NULL length=0
void insfirst(LISTHEADP h,DULNODEP s);//insfirst  insert one node at first postion length=0
void delfirst(LISTHEADP h); //delete first node current_point to next node
void inslast(LISTHEADP h,DULNODEP s); //inslast  insert one node at last postion
void dellast(LISTHEADP h) ; //delete last node current_point to prior node
void addnode(DULNODEP inode,int postion,LISTHEADP h);//insert one node after postion 
void removenode(int postion,LISTHEADP h) ;//delete node at give postion 
void replacenode(int postion,LISTHEADP h,DULNODEP inode);//replace one node
void viewchain(LISTHEADP h);//show info for chain
void viewheadinfo(LISTHEADP h);//only show head info

我將上一節演示的頭結點增加了last指標指向最後一個節點,同時增加了current指標指向操作的指標。結構體如下:
typedef struct listhead
{
        DULNODEP head;
        DULNODEP last;
        DULNODEP current;
        int length;
} LISTHEAD,*LISTHEADP;

這樣我們在實現inslastdellast的時候變得非常簡單了,而delfirstinsfirst本來就是透過head指標實現的,如果大家對棧和佇列的實現有了解,著4個函式可以用來實現他們,這個我會在隨後進行說明,這裡只考慮雙線連結串列,我基本上用註釋解釋了全部了功能下面一張圖大概看看雙向連結串列的結構,假設Noden為插入的節點就是如下,刪除也差不多沒畫




下面以程式碼的方式給出實現:

點選(此處)摺疊或開啟

  1. 標頭檔案:
  2. //error(1):delfirst() error list have no
  3. //error(2):getelemp() postion large than lenth or poastion = 0
  4. //error(3):viewchain() list no data

  5. #ifndef _liststr_
  6. #define _liststr_
  7. #define bool int
  8. #define true 1
  9. #define false 0
  10. typedef struct dulnode //node type
  11. {
  12.         int data; //example
  13.         struct dulnode *prior;
  14.         struct dulnode *next;
  15. } DULNODE,*DULNODEP;

  16. typedef struct listhead
  17. {
  18.         DULNODEP head;
  19.         DULNODEP last;
  20.         DULNODEP current;
  21.         int length;
  22. } LISTHEAD,*LISTHEADP;

  23. #define SIZENODE sizeof(DULNODE)
  24. #define SIZELISTHEAD sizeof(LISTHEAD)

  25. bool makenode(int datavalue,DULNODEP* p); //makenode next and prior is NULL
  26. void freenode(DULNODEP p); //freenode
  27. bool initlist(LISTHEADP* p); //initlist with no node head last current pointor is NULL
  28. void destroylist(LISTHEADP p); //destroy a list,every list thing is not live
  29. void clearlist(LISTHEADP p);//clear a list,but head is live and head last current pointor is NULL length=0
  30. void insfirst(LISTHEADP h,DULNODEP s);//insfirst insert one node at first postion length=0
  31. void delfirst(LISTHEADP h); //delete first node current_point to next node
  32. void inslast(LISTHEADP h,DULNODEP s); //inslast insert one node at last postion
  33. void dellast(LISTHEADP h) ; //delete last node current_point to prior node
  34. void addnode(DULNODEP inode,int postion,LISTHEADP h);//insert one elem after postion
  35. void removenode(int postion,LISTHEADP h) ;//delete elem at give postion
  36. void replacenode(int postion,LISTHEADP h,DULNODEP inode);//replace one node
  37. void viewchain(LISTHEADP h);//show info for chain
  38. void viewheadinfo(LISTHEADP h);//only show head info

  39. #endif

點選(此處)摺疊或開啟

  1. 功能函式檔案:
  2. #include<stdlib.h>
  3. #include<stdio.h>
  4. #include <string.h>
  5. #include"dulnode.h"

  6. static DULNODEP getelemp(const LISTHEADP h,int postion) ;

  7. //makenode
  8. bool makenode(int datavalue,DULNODEP* p)
  9. {
  10.         *p = (DULNODEP) malloc (SIZENODE);
  11.         if(!(*p))
  12.         {
  13.                 return false;
  14.         }
  15.         else
  16.         {
  17.                 memset(*p,0,SIZENODE);
  18.                 (*p)->data = datavalue;
  19.                 (*p)->next = NULL;
  20.                 (*p)->prior = NULL;
  21.                 return true;
  22.         }
  23. }

  24. //freenode

  25. void freenode(DULNODEP p)
  26. {
  27.         free(p);
  28. }

  29. //initlist with no node

  30. bool initlist(LISTHEADP* p)
  31. {
  32.         *p = (LISTHEADP)malloc(SIZELISTHEAD);
  33.         if(!*p)
  34.         {
  35.                 return false;
  36.         }
  37.         else
  38.         {
  39.                 memset(*p,0,SIZELISTHEAD);
  40.                 (*p)->head = NULL;
  41.                 (*p)->last = NULL;
  42.                 (*p)->current = NULL;
  43.                 (*p)->length = 0;
  44.                 return true;
  45.         }
  46. }
  47. //destroy a list,every list thing is not live
  48. void destroylist(LISTHEADP p)
  49. {
  50.         DULNODEP npc;
  51.         DULNODEP npn;
  52.         int i = 0;

  53.         if(npc = p->head)
  54.         {
  55.                 npn = p->head->next;
  56.                 for(i=0;i<p->length;i++)
  57.                 {
  58.                         free(npc);
  59.                         npc = npn;
  60.                         if(npn) //last one is null null->next will
  61.                         {
  62.                                 npn = npn->next;
  63.                         }
  64.                 }
  65.         }

  66.         free(p);
  67. }
  68. //clear a list,but head is live
  69. void clearlist(LISTHEADP p)
  70. {
  71.         DULNODEP npc;
  72.         DULNODEP npn;
  73.         int i = 0;

  74.         if(npc = p->head)
  75.         {
  76.                 npn = p->head->next;
  77.                 for(i=0;i<p->length;i++)
  78.                 {
  79.                         free(npc);
  80.                         npc = npn;
  81.                         if(npn) //last one is null null->next will
  82.                         {
  83.                                 npn = npn->next;
  84.                         }
  85.                 }
  86.         }
  87.         p->head = NULL;
  88.         p->last = NULL;
  89.         p->current = NULL;
  90.         p->length = 0;
  91. }

  92. //insfirst insert one node at first postion

  93. void insfirst(LISTHEADP h,DULNODEP s)
  94. {
  95.         if(!(h->head)) //list is empty or not
  96.         {
  97.                 h->head = s;
  98.                 h->last = s;
  99.                 h->current = s;
  100.                 h->length++;
  101.         }
  102.         else
  103.         {
  104.                 h->head->prior = s;
  105.                 s ->next = h->head;
  106.                 h->head = s;
  107.                 h->current = s;
  108.                 h->length++;

  109.         }

  110. }


  111. //delfirst
  112. void delfirst(LISTHEADP h) //delete first node current_point to next node
  113. {
  114.         DULNODEP p;
  115.         if(!(h->head))
  116.         {
  117.                 printf("error(1):delfirst() error list have no node!\n");
  118.                 exit(1);
  119.         }
  120.         else if(!(h->head->next)) //only one node
  121.         {
  122.                 free(h->head);
  123.                 h->head = NULL;
  124.                 h->current = NULL;
  125.                 h->last = NULL;
  126.                 h->length--;
  127.         }
  128.         else
  129.         {
  130.                 p = h->head ;
  131.                 h->head->next->prior = NULL;
  132.                 h->head = h->head->next;
  133.                 h->current = h->head;
  134.                 h->length--;
  135.                 free(p);
  136.         }
  137. }


  138. //inslast insert one node at last postion

  139. void inslast(LISTHEADP h,DULNODEP s)
  140. {
  141.         if(!(h->head)) //list is empty or not
  142.         {
  143.                 h->head = s;
  144.                 h->last = s;
  145.                 h->current = s;
  146.                 h->length++;
  147.         }
  148.         else
  149.         {
  150.                 h->last->next = s;
  151.                 s->prior = h->last;
  152.                 h->last = s;
  153.                 h->current = s;
  154.                 h->length++;
  155.         }
  156. }



  157. //dellast

  158. void dellast(LISTHEADP h) //delete last node current_point to prior node
  159. {
  160.         DULNODEP p;
  161.         if(!(h->head))
  162.         {
  163.                 printf("error(1):delfirst() error list have no node!\n");
  164.                 exit(1);
  165.         }
  166.         else if(!(h->head->next)) //only one node
  167.         {
  168.                 free(h->head);
  169.                 h->head = NULL;
  170.                 h->current = NULL;
  171.                 h->last = NULL;
  172.                 h->length--;
  173.         }
  174.         else
  175.         {
  176.                 p = h->last ;
  177.                 h->last->prior->next = NULL;
  178.                 h->last = p->prior;
  179.                 h->current = p->prior;
  180.                 h->length--;
  181.                 free(p);
  182.         }
  183. }


  184. static DULNODEP getelemp(const LISTHEADP h,int postion)
  185. {
  186.         int i=0;
  187.         DULNODEP p;
  188.         if(postion > h->length || postion ==0 )
  189.         {
  190.                 printf("error(2):getelemp() postion large than lenth or poastion = 0\n");
  191.                 exit(2);
  192.         }
  193.         p = h->head;

  194.         while(i<postion-1)
  195.         {
  196.                 i++;
  197.                 p = p->next;
  198.         }
  199.         return p;
  200. }

  201. //addnode add one node after give postion
  202. void addnode(DULNODEP inode,int postion,LISTHEADP h) //insert one elem after postion
  203. {
  204.         DULNODEP p;
  205.         p = getelemp(h,postion);
  206.         if(!p->next) //last node?
  207.         {
  208.                 p->next = inode;
  209.                 inode->prior = p;
  210.                 inode->next = NULL;
  211.                 h->last = inode;
  212.                 h->current = inode;
  213.         }
  214.         else
  215.         {
  216.                 inode->prior = p;
  217.                 inode->next = p->next;
  218.                 p->next->prior = inode;
  219.                 p->next = inode;
  220.                 h->current = inode;
  221.         }
  222.         h->length++;
  223. }

  224. //removenode remove one node at postion and current point to next postion

  225. void removenode(int postion,LISTHEADP h) //delete elem at give postion
  226. {
  227.         DULNODEP p;
  228.         p = getelemp(h,postion);

  229.         if(postion == 1 && !(p->next)) //node one and only one node
  230.         {
  231.                 h->head = NULL;
  232.                 h->current = NULL;
  233.                 h->last = NULL;
  234.                 free(p);
  235.         }
  236.         else if(postion == 1) //node one?
  237.         {
  238.                 p->next->prior = NULL;
  239.                 h->head = p->next;
  240.                 h->current = h->head;
  241.                 free(p);
  242.         }
  243.         else if(!(p->next)) //last node?
  244.         {
  245.                 h->current = NULL;
  246.                 h->last = p->prior;
  247.                 p->prior->next = NULL;
  248.                 free(p);
  249.         }
  250.         else
  251.         {
  252.                 h->current = p->next;
  253.                 p->next->prior = p->prior;
  254.                 p->prior->next = p->next;
  255.                 free(p);
  256.         }
  257.         h->length--;
  258. }


  259. //replacenode replace one node


  260. void replacenode(int postion,LISTHEADP h,DULNODEP inode)
  261. {
  262.         DULNODEP p;
  263.         p = getelemp(h,postion);

  264.         if(postion == 1 && !(p->next)) //node one and only one node
  265.         {
  266.                 h->head = inode;
  267.                 h->current = inode;
  268.                 h->last = inode;
  269.                 free(p);
  270.         }
  271.         else if(postion == 1)
  272.         {
  273.                 inode->next = h->head->next;
  274.                 h->head->next->prior = inode;
  275.                 h->head = inode;
  276.                 h->current = inode;
  277.                 free(p);
  278.         }
  279.         else if(!(p->next))
  280.         {
  281.                 inode->prior = p->prior;
  282.                 p->prior->next = inode;
  283.                 h->current = inode;
  284.                 h->last = inode;
  285.                 free(p);
  286.         }
  287.         else
  288.         {
  289.                 inode->prior = p->prior;
  290.                 inode->next = p->next;
  291.                 p->prior->next = inode;
  292.                 p->next->prior = inode;
  293.                 h->current = inode;
  294.                 free(p);
  295.         }
  296. }


  297. void viewchain(LISTHEADP h)
  298. {
  299.         int i=1;
  300.         DULNODEP p;
  301.         p = h->head;
  302.         if(!p)
  303.         {
  304.                 printf("error(3):viewchain() list no data\n");
  305.                 exit(3);
  306.         }

  307.         printf("Max chain length is:%d,current_pointor is:%p,head_pointor is:%p,last_pointor is:%p\n",h->length,h->current,h->head,h->last);
  308.         do
  309.         {
  310.                 printf("node:%d values is: %d\n",i,p->data);
  311.                 i++;

  312.         }while(p=p->next);
  313. }

  314. void viewheadinfo(LISTHEADP h)
  315. {

  316.         printf("Max chain length is:%d,current_pointor is:%p,head_pointor is:%p,last_pointor is:%p\n",h->length,h->current,h->head,h->last);
  317. }

點選(此處)摺疊或開啟

  1. 主函式檔案:
  2. #include<stdlib.h>
  3. #include<stdio.h>
  4. #include"dulnode.h"



  5. int main(void)
  6. {
  7.         LISTHEADP headp=NULL;
  8.         DULNODEP p1=NULL;
  9.         DULNODEP p2=NULL;
  10.         DULNODEP p3=NULL;
  11.         DULNODEP p4=NULL;

  12.         DULNODEP p5=NULL;
  13.         DULNODEP p6=NULL;

  14.         if(!(initlist(&headp)))
  15.                 {
  16.                         printf("initlist error\n");
  17.                 }
  18.         if(!(makenode(1,&p1)))
  19.                 {
  20.                         printf("makenode error\n");
  21.                 }
  22.         if(!(makenode(2,&p2)))
  23.         {
  24.                 printf("makenode error\n");
  25.         }
  26.         if(!(makenode(3,&p3)))
  27.         {
  28.                  printf("makenode error\n");
  29.         }
  30.         if(!(makenode(4,&p4)))
  31.         {
  32.                 printf("makenode error\n");
  33.         }

  34.         if(!(makenode(5,&p5)))
  35.         {
  36.                 printf("makenode error\n");
  37.         }

  38.         if(!(makenode(6,&p6)))
  39.         {
  40.                 printf("makenode error\n");
  41.         }

  42.         insfirst(headp,p1);
  43.         insfirst(headp,p2);
  44.         insfirst(headp,p3);
  45.         inslast(headp,p4);

  46.         viewchain(headp);

  47.         delfirst(headp);
  48.         viewchain(headp);
  49.         dellast(headp);
  50.         viewchain(headp);

  51.         addnode(p5,1,headp);
  52.         viewchain(headp);
  53.         replacenode(2,headp,p6);
  54.         viewchain(headp);
  55.         removenode(2,headp);
  56.         viewchain(headp);
  57.         clearlist(headp);
  58.         destroylist(headp);
  59.         return 0;

  60. }

下面我們給出結果來分析:
Max chain length is:4,current_pointor is:0xd210a0,head_pointor is:0xd21080,last_pointor is:0xd210a0
node:1 values is: 3
node:2 values is: 2
node:3 values is: 1
node:4 values is: 4
Max chain length is:3,current_pointor is:0xd21060,head_pointor is:0xd21060,last_pointor is:0xd210a0
node:1 values is: 2
node:2 values is: 1
node:3 values is: 4
Max chain length is:2,current_pointor is:0xd21040,head_pointor is:0xd21060,last_pointor is:0xd21040
node:1 values is: 2
node:2 values is: 1
Max chain length is:3,current_pointor is:0xd210c0,head_pointor is:0xd21060,last_pointor is:0xd21040
node:1 values is: 2
node:2 values is: 5
node:3 values is: 1
Max chain length is:3,current_pointor is:0xd210e0,head_pointor is:0xd21060,last_pointor is:0xd21040
node:1 values is: 2
node:2 values is: 6
node:3 values is: 1
Max chain length is:2,current_pointor is:0xd21040,head_pointor is:0xd21060,last_pointor is:0xd21040
node:1 values is: 2
node:2 values is: 1

首先構造了4個節點前面3個用insfrist 這樣就是 3 2 1的排列最後一個用inslast 那麼就是 3 2 1 4 可以看到確實如此

然後使用delfrist 刪除第一個就是3 那麼剩下 2 1 4 然後使用dellast 那麼刪除 4 就是 2 1 可以看到確實如此

然後我們使用addnode 在位置1後面加入元素 5 那麼就是 2 5 1 確實如此
然後我們使用replacenode 將位置2的元素 data 5的資料換位 data為 6的資料變為 2 6 1
最後呼叫removenode將位置2的元素刪除變為了 2 1 最後是清空和銷燬連結串列。
整個過程預期和測試結果一致

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2125114/,如需轉載,請註明出處,否則將追究法律責任。

相關文章