zoukankan      html  css  js  c++  java
  • 双向链表

    来源:http://blog.csdn.net/hopeyouknow/article/details/6716177

    首先编写头文件,头文件里做相关的定义和声明,DList.h内容如下:

    1. #ifndef DList_H  
    2. #define DList_H  
    3. typedef  int Item;  
    4. typedef struct Node * PNode;  
    5. typedef PNode Position;  
    6. /*定义节点类型*/  
    7. typedef struct Node  
    8. {  
    9.     Item data;      /*数据域*/  
    10.     PNode previous; /*指向前驱*/  
    11.     PNode next;     /*指向后继*/  
    12. }Node;  
    13. /*定义链表类型*/  
    14. typedef struct  
    15. {  
    16.     PNode head;     /*指向头节点*/  
    17.     PNode tail;     /*指向尾节点*/  
    18.     int size;  
    19. }DList;  
    20.   
    21. /*分配值为i的节点,并返回节点地址*/  
    22. Position MakeNode(Item i);  
    23.   
    24. /*释放p所指的节点*/  
    25. void FreeNode(PNode p);  
    26.   
    27. /*构造一个空的双向链表*/  
    28. DList* InitList();  
    29.   
    30. /*摧毁一个双向链表*/  
    31. void DestroyList(DList *plist);  
    32.   
    33. /*将一个链表置为空表,释放原链表节点空间*/  
    34. void ClearList(DList *plist);  
    35.   
    36. /*返回头节点地址*/  
    37. Position GetHead(DList *plist);  
    38.   
    39. /*返回尾节点地址*/  
    40. Position GetTail(DList *plist);  
    41.   
    42. /*返回链表大小*/  
    43. int GetSize(DList *plist);  
    44.   
    45. /*返回p的直接后继位置*/  
    46. Position GetNext(Position p);  
    47.   
    48. /*返回p的直接前驱位置*/  
    49. Position GetPrevious(Position p);  
    50.   
    51. /*将pnode所指节点插入第一个节点之前*/  
    52. PNode InsFirst(DList *plist,PNode pnode);  
    53.   
    54. /*将链表第一个节点删除并返回其地址*/  
    55. PNode DelFirst(DList *plist);  
    56.   
    57. /*获得节点的数据项*/  
    58. Item GetItem(Position p);  
    59.   
    60. /*设置节点的数据项*/  
    61. void SetItem(Position p,Item i);  
    62.   
    63. /*删除链表中的尾节点并返回其地址,改变链表的尾指针指向新的尾节点*/  
    64. PNode Remove(DList *plist);  
    65.   
    66. /*在链表中p位置之前插入新节点S*/  
    67. PNode InsBefore(DList *plist,Position p,PNode s);  
    68.   
    69. /*在链表中p位置之后插入新节点s*/  
    70. PNode InsAfter(DList *plist,Position p,PNode s);  
    71.   
    72. /*返回在链表中第i个节点的位置*/  
    73. PNode LocatePos(DList *plist,int i);  
    74.   
    75. /*依次对链表中每个元素调用函数visit()*/  
    76. void ListTraverse(DList *plist,void (*visit)());  
    77. #endif  


    接下来逐个实现其功能,DList.c内容如下:

    1. #include"DList.h"  
    2. #include<malloc.h>  
    3. #include<stdlib.h>  
    4. /*分配值为i的节点,并返回节点地址*/  
    5. Position MakeNode(Item i)  
    6. {  
    7.     PNode p = NULL;   
    8.     p = (PNode)malloc(sizeof(Node));  
    9.     if(p!=NULL)  
    10.     {  
    11.         p->data = i;  
    12.         p->previous = NULL;  
    13.         p->next = NULL;  
    14.     }     
    15.     return p;  
    16. }  
    17. /*释放p所指的节点*/  
    18. void FreeNode(PNode p)  
    19. {  
    20.      free(p);  
    21. }  
    22. /*构造一个空的双向链表*/  
    23. DList * InitList()  
    24. {  
    25.     DList *plist = (DList *)malloc(sizeof(DList));  
    26.     PNode head = MakeNode(0);   
    27.     if(plist!=NULL)  
    28.     {  
    29.         if(head!=NULL)  
    30.         {  
    31.             plist->head = head;  
    32.             plist->tail = head;  
    33.             plist->size = 0;  
    34.         }  
    35.         else  
    36.             return NULL;  
    37.     }  
    38.     return plist;  
    39. }  
    40.   
    41. /*摧毁一个双向链表*/  
    42. void DestroyList(DList *plist)  
    43. {  
    44.     ClearList(plist);  
    45.     free(GetHead(plist));  
    46.     free(plist);  
    47. }  
    48.   
    49. /*判断链表是否为空表*/  
    50. int IsEmpty(DList *plist)  
    51. {  
    52.     if(GetSize(plist)==0&&GetTail(plist)==GetHead(plist))  
    53.         return 1;  
    54.     else  
    55.         return 0;  
    56. }  
    57. /*将一个链表置为空表,释放原链表节点空间*/  
    58. void ClearList(DList *plist)  
    59. {  
    60.     PNode temp,p;  
    61.     p = GetTail(plist);  
    62.     while(!IsEmpty(plist))  
    63.     {     
    64.         temp = GetPrevious(p);  
    65.         FreeNode(p);  
    66.         p = temp;  
    67.         plist->tail = temp;  
    68.         plist->size--;  
    69.     }  
    70. }  
    71.   
    72. /*返回头节点地址*/  
    73. Position GetHead(DList *plist)  
    74. {  
    75.     return plist->head;  
    76. }  
    77.   
    78. /*返回尾节点地址*/  
    79. Position GetTail(DList *plist)  
    80. {  
    81.     return plist->tail;  
    82. }  
    83.   
    84. /*返回链表大小*/  
    85. int GetSize(DList *plist)  
    86. {  
    87.     return plist->size;  
    88. }  
    89.   
    90. /*返回p的直接后继位置*/  
    91. Position GetNext(Position p)  
    92. {  
    93.     return p->next;  
    94. }  
    95.   
    96. /*返回p的直接前驱位置*/  
    97. Position GetPrevious(Position p)  
    98. {  
    99.     return p->previous;  
    100. }  
    101.   
    102. /*将pnode所指节点插入第一个节点之前*/  
    103. PNode InsFirst(DList *plist,PNode pnode)  
    104. {  
    105.     Position head = GetHead(plist);  
    106.   
    107.     if(IsEmpty(plist))  
    108.         plist->tail = pnode;  
    109.     plist->size++;  
    110.   
    111.     pnode->next = head->next;  
    112.     pnode->previous = head;  
    113.   
    114.     if(head->next!=NULL)  
    115.         head->next->previous = pnode;  
    116.     head->next = pnode;  
    117.       
    118.     return pnode;   
    119. }  
    120.   
    121. /*将链表第一个节点删除,返回该节点的地址*/  
    122. PNode DelFirst(DList *plist)  
    123. {  
    124.     Position head = GetHead(plist);  
    125.     Position p=head->next;  
    126.     if(p!=NULL)  
    127.     {  
    128.         if(p==GetTail(plist))  
    129.             plist->tail = p->previous;  
    130.         head->next = p->next;  
    131.         head->next->previous = head;  
    132.         plist->size--;  
    133.           
    134.     }     
    135.     return p;  
    136. }  
    137.   
    138. /*获得节点的数据项*/  
    139. Item GetItem(Position p)  
    140. {  
    141.     return p->data;  
    142. }  
    143.   
    144. /*设置节点的数据项*/  
    145. void SetItem(Position p,Item i)  
    146. {  
    147.     p->data = i;  
    148. }  
    149.   
    150. /*删除链表中的尾节点并返回地址,改变链表的尾指针指向新的尾节点*/  
    151. PNode Remove(DList *plist)  
    152. {  
    153.     Position p=NULL;  
    154.     if(IsEmpty(plist))  
    155.         return NULL;  
    156.     else  
    157.     {  
    158.         p = GetTail(plist);  
    159.         p->previous->next = p->next;  
    160.         plist->tail = p->previous;  
    161.         plist->size--;  
    162.         return p;  
    163.     }  
    164. }  
    165. /*在链表中p位置之前插入新节点s*/  
    166. PNode InsBefore(DList *plist,Position p,PNode s)  
    167. {  
    168.     s->previous = p->previous;  
    169.     s->next = p;  
    170.     p->previous->next = s;      
    171.     p->previous = s;  
    172.   
    173.     plist->size++;  
    174.     return s;  
    175. }  
    176. /*在链表中p位置之后插入新节点s*/  
    177. PNode InsAfter(DList *plist,Position p,PNode s)  
    178. {  
    179.     s->next = p->next;  
    180.     s->previous = p;  
    181.       
    182.     if(p->next != NULL)  
    183.         p->next->previous = s;  
    184.     p->next = s;  
    185.       
    186.     if(p = GetTail(plist))  
    187.         plist->tail = s;  
    188.       
    189.     plist->size++;  
    190.     return s;  
    191. }  
    192.   
    193. /*返回在链表中第i个节点的位置*/  
    194. PNode LocatePos(DList *plist,int i)  
    195. {  
    196.     int cnt = 0;  
    197.     Position p = GetHead(plist);  
    198.     if(i>GetSize(plist)||i<1)  
    199.         return NULL;  
    200.   
    201.     while(++cnt<=i)  
    202.     {  
    203.         p=p->next;  
    204.     }  
    205.   
    206.     return p;  
    207. }  
    208.   
    209. /*依次对链表中每个元素调用函数visit()*/  
    210. void ListTraverse(DList *plist,void (*visit)())  
    211. {  
    212.     Position p = GetHead(plist);  
    213.     if(IsEmpty(plist))  
    214.         exit(0);  
    215.     else  
    216.     {  
    217.           
    218.         while(p->next!=NULL)  
    219.         {  
    220.             p = p->next;  
    221.             visit(p->data);            
    222.         }         
    223.     }  
    224. }  


    接下来进行测试,Test.h内容如下:

    1. #include"DList.h"  
    2. #include<stdio.h>  
    3. void print(Item i)  
    4. {  
    5.     printf("数据项为%d  ",i);  
    6. }  
    7. main()  
    8. {  
    9.     DList *plist = NULL;  
    10.     PNode p = NULL;  
    11.       
    12.     plist = InitList();  
    13.     p = InsFirst(plist,MakeNode(1));  
    14.     InsBefore(plist,p,MakeNode(2));  
    15.     InsAfter(plist,p,MakeNode(3));  
    16.   
    17.     printf("p前驱位置的值为%d ",GetItem(GetPrevious(p)));  
    18.     printf("p位置的值为%d ",GetItem(p));  
    19.     printf("p后继位置的值为%d ",GetItem(GetNext(p)));  
    20.       
    21.       
    22.     printf("遍历输出各节点数据项: ");  
    23.     ListTraverse(plist,print);  
    24.     printf("除了头节点该链表共有%d个节点 ",GetSize(plist));  
    25.     FreeNode(DelFirst(plist));  
    26.     printf("删除第一个节点后重新遍历输出为: ");  
    27.     ListTraverse(plist,print);  
    28.     printf("除了头节点该链表共有%d个节点 ",GetSize(plist));  
    29.     DestroyList(plist);  
    30.     printf("链表已被销毁 ");  
    31. }  
  • 相关阅读:
    C# 实现任务栏图标程序
    C#实现的木马之客户端
    sql基本语法
    水晶报表引用DataSet做数据源
    解决多线程操作控件时可能出现的异常:“在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级”
    电子书籍制作工具软件大全
    C#实现的木马之服务端
    2进制、8进制、10进制、16进制...各种进制间的轻松转换
    VC# .Net中使用Crystal Report水晶报表
    P2P技术学习
  • 原文地址:https://www.cnblogs.com/heyonggang/p/3272639.html
Copyright © 2011-2022 走看看