飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 2855|回复: 1

[C/C++] 学习Nisy的C教程第31课--链表双链

[复制链接]
  • TA的每日心情
    开心
    2018-9-27 19:17
  • 签到天数: 31 天

    [LV.5]常住居民I

    发表于 2015-2-8 11:17:36 | 显示全部楼层 |阅读模式
    本帖最后由 lucky_789 于 2015-2-8 12:03 编辑

    第30课视频教程两个半小时,看了几次才看完{:soso_e110:},模仿着写了个简单的链表和双链。欢迎大家提出宝贵意见。
    一、单向链表

    1. /* list1.h -- 单向链表头文件   */

    2. #define NULL 0

    3. typedef int ElementType;

    4. typedef struct _ChainNode
    5. {
    6.         ElementType data;
    7.         struct _ChainNode *next;
    8. }ChainNode;

    9. typedef struct
    10. {
    11.         ChainNode *head;
    12.         ChainNode *tail;
    13.         int total;
    14. }List;

    15. List * ListInit();

    16. /* 销毁链表 */
    17. int ListDestory(List *lp);

    18. /* 向链首插入节点 */
    19. int InsertHead(List *lp, ElementType *pdata);

    20. /* 向链尾插入节点 */
    21. int InsertTail(List *lp, ElementType *pdata);

    22. /* 向链中间插入节点 */
    23. int InsertNode(List *lp, int n, ElementType *pdata);

    24. /* 清空链表 */
    25. int ListClear(List *lp);

    26. /*删除节点 */
    27. int RemoveNode(List *lp, int n);

    28. /* 新建节点 */
    29. ChainNode * NewChainNode(ElementType *pdata);

    30. /* 查找节点 */
    31. ChainNode * GetChainNode(List *lp, int n);

    32. int IsEmpty(List *lp);

    33. /* 遍历显示链表 */
    34. int ListTraverse(List * lp, void (*f)(ElementType *pdata));
    复制代码

    1. /* list1.c -- 单向链表    */

    2. #include "list1.h"

    3. List * ListInit()
    4. {
    5.         List *lp = NULL;
    6.         lp = (List *)malloc(sizeof(List));
    7.         lp->head = NULL;
    8.         lp->tail = NULL;
    9.         lp->total = 0;
    10.         return lp;
    11. }

    12. int ListDestory(List *lp)
    13. {
    14.         ChainNode *p = NULL;
    15.         ChainNode *tmp = NULL;
    16.         if(!lp)
    17.                 return 0;
    18.         p = lp->head;
    19.         while(p)
    20.         {
    21.                 tmp = p->next;
    22.                 free(p);
    23.                 p = tmp;
    24.         }
    25.         free(lp);        
    26.         return 1;
    27. }

    28. int ListClear(List *lp)
    29. {
    30.         ChainNode *p = NULL;
    31.         ChainNode *tmp = NULL;
    32.         if(!lp) return 0;

    33.         p = lp->head;
    34.         while(p)
    35.         {
    36.                 tmp = p->next;
    37.                 free(p);
    38.                 p = tmp;
    39.         }
    40.         lp->head = NULL;        
    41.         lp->tail = NULL;
    42.         lp->total = 0;
    43.         return 1;
    44. }

    45. int InsertHead(List *lp, ElementType *pdata)
    46. {
    47.         ChainNode *newp = NULL;

    48.         if(!lp) return 0;

    49.         newp = NewChainNode(pdata);
    50.         if(!newp) return 0;

    51.         if(IsEmpty(lp))
    52.         {
    53.                 /* 为空则以此为首节点和尾节点 */
    54.                 lp->head = lp->tail = newp;
    55.                 lp->total++;
    56.         }
    57.         else
    58.         {
    59.                 /* 非空则以新节点为首节点 */
    60.                 newp->next = lp->head;
    61.                 lp->head = newp;
    62.                 lp->total++;
    63.         }
    64.         return 1;
    65. }

    66. int InsertTail(List *lp, ElementType *pdata)
    67. {
    68.         ChainNode *newp = NULL;

    69.         if(!lp) return 0;

    70.         newp = NewChainNode(pdata);
    71.         if(!newp) return 0;

    72.         if(IsEmpty(lp))
    73.         {
    74.                 /* 为空则以此为首节点和尾节点 */
    75.                 lp->head = lp->tail = newp;
    76.                 lp->total++;
    77.         }
    78.         else
    79.         {
    80.                 /* 非空则以新节点为尾节点 */
    81.                 (lp->tail)->next = newp;
    82.                 lp->tail = newp;
    83.                 lp->total++;
    84.         }
    85.         return 1;
    86. }

    87. int InsertNode(List *lp, int n, ElementType *pdata)
    88. {
    89.         ChainNode *p = NULL;
    90.         ChainNode *newp = NULL;

    91.         if(!lp) return 0;
    92.         if(n <= 1 || n > lp->total) return 0;

    93.         p = GetChainNode(lp, n - 1);
    94.         if(!p) return 0;

    95.         newp = NewChainNode(pdata);
    96.         if(!newp) return 0;

    97.         newp->next = p->next;
    98.         p->next = newp;
    99.         lp->total++;
    100.         return 1;
    101. }

    102. int RemoveNode(List *lp, int n)
    103. {
    104.         ChainNode *p = NULL;
    105.         ChainNode *tmp = NULL;

    106.         if(!lp) return 0;
    107.         if(n < 1 || n > lp->total) return 0;

    108.         if(lp->total == 1)
    109.         {
    110.                 free(lp->head);
    111.                 lp->head = NULL;
    112.                 lp->tail = NULL;
    113.                 lp->total = 0;
    114.         }
    115.         else
    116.         {
    117.                 if(n == 1)
    118.                 {
    119.                         tmp = (lp->head)->next;
    120.                         free(lp->head);
    121.                         lp->head = tmp;
    122.                         lp->total--;
    123.                 }
    124.                 else if(n == lp->total)
    125.                 {
    126.                         p = GetChainNode(lp, n - 1);
    127.                         p->next = NULL;
    128.                         free(lp->tail);
    129.                         lp->tail = p;
    130.                         lp->total--;
    131.                 }
    132.                 else
    133.                 {
    134.                         p = GetChainNode(lp, n - 1);
    135.                         tmp = (p->next)->next;
    136.                         free(p->next);
    137.                         p->next = tmp;
    138.                         lp->total--;
    139.                 }
    140.         }
    141.         return 1;
    142. }

    143. ChainNode * NewChainNode(ElementType *pdata)
    144. {
    145.         ChainNode *p = NULL;
    146.         p = (ChainNode *)malloc(sizeof(ChainNode));
    147.         if(!p) return p;
    148.         memcpy(&p->data, pdata, sizeof(ElementType));
    149.         p->next = NULL;
    150.         return p;
    151. }

    152. int IsEmpty(List *lp)
    153. {
    154.         return lp->total == 0;
    155. }

    156. ChainNode * GetChainNode(List *lp, int n)
    157. {
    158.         ChainNode *p = NULL;
    159.         int i = 0;

    160.         if(!lp) return 0;
    161.         if(n < 1 || n > lp->total) return 0;

    162.         for(i = 1, p = lp->head; i < n; i++, p = p->next);

    163.         return p;
    164. }

    165. int ListTraverse(List * lp, void (*pfn)(ElementType *pdata))
    166. {
    167.         int i = 0;
    168.         ChainNode *p = NULL;
    169.         if(!lp) return 0;
    170.         /* for (p = lp->head; p; p = p->next) */
    171.         for (p = lp->head, i = 0; i < lp->total; i++, p = p->next)
    172.                 pfn(&p->data);
    173.         printf("\n");
    174.         return 1;
    175. }
    复制代码

    1. /* test1.c -- 单向链表     */
    2. /* 和list1.c一起编译       */


    3. #include "List1.h"

    4. void myprintf(ElementType * pdata)
    5. {
    6.         printf("%d ", *pdata);
    7. }

    8. int main()
    9. {
    10.         int i;
    11.         List *lp = ListInit();
    12.         ElementType a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    13.         ElementType data = 99;

    14.         if(!lp)
    15.         {
    16.                 printf("\nInitList error!\n");
    17.                 return 0;
    18.         }

    19.         for (i = 0; i < 10; i++)
    20.         {
    21.                 InsertTail(lp, a+i);
    22.         }

    23.         ListTraverse(lp, myprintf);

    24.         InsertHead(lp, &data);
    25.         ListTraverse(lp, myprintf);

    26.         InsertTail(lp, &data);
    27.         ListTraverse(lp, myprintf);

    28.         InsertNode(lp, 3, &data);
    29.         ListTraverse(lp, myprintf);

    30.         RemoveNode(lp, 3);
    31.         ListTraverse(lp, myprintf);

    32.         RemoveNode(lp, 12);
    33.         ListTraverse(lp, myprintf);

    34.         RemoveNode(lp, 1);
    35.         ListTraverse(lp, myprintf);

    36.         ListDestory(lp);
    37.         return 1;
    38. }
    复制代码


    二、双向链表(在单向链表的基础上略加修改而来)

    1. /* list2.h -- 双向链表头文件     */

    2. #define NULL 0

    3. typedef int ElementType;

    4. typedef struct _ChainNode
    5. {
    6.         struct _ChainNode *prev;
    7.         ElementType data;
    8.         struct _ChainNode *next;
    9. }ChainNode;

    10. typedef struct
    11. {
    12.         ChainNode *head;
    13.         ChainNode *tail;
    14.         int total;  /* 保留此项主要是考虑以空间换时间。其实程序体还节省了更多的代码空间 */
    15. }List;

    16. List * ListInit();

    17. int ListDestory(List *lp);

    18. int InsertHead(List *lp, ElementType *pdata);

    19. int InsertTail(List *lp, ElementType *pdata);

    20. int InsertNode(List *lp, int n, ElementType *pdata);

    21. int ListClear(List *lp);

    22. int RemoveNode(List *lp, int n);

    23. ChainNode * NewChainNode(ElementType *pdata);

    24. ChainNode * GetChainNode(List *lp, int n);

    25. int IsEmpty(List *lp);

    26. int ListTraverse(List * lp, void (*f)(ElementType *pdata));
    复制代码

    1. /* list2.c -- 双向链表      */

    2. #include "list2.h"

    3. List * ListInit()
    4. {
    5.         List *lp = NULL;
    6.         lp = (List *)malloc(sizeof(List));
    7.         lp->head = NULL;
    8.         lp->tail = NULL;
    9.         lp->total = 0;
    10.         return lp;
    11. }

    12. int ListDestory(List *lp)
    13. {
    14.         ChainNode *p = NULL;
    15.         ChainNode *tmp = NULL;
    16.         if(!lp) return 0;

    17.         p = lp->head;
    18.         while(p)
    19.         {
    20.                 tmp = p->next;
    21.                 free(p);
    22.                 p = tmp;
    23.         }
    24.         free(lp);        
    25.         return 1;
    26. }

    27. int ListClear(List *lp)
    28. {
    29.         ChainNode *p = NULL;
    30.         ChainNode *tmp = NULL;
    31.         if(!lp) return 0;

    32.         p = lp->head;
    33.         while(p)
    34.         {
    35.                 tmp = p->next;
    36.                 free(p);
    37.                 p = tmp;
    38.         }

    39.         lp->head = NULL;        
    40.         lp->tail = NULL;
    41.         lp->total = 0;
    42.         return 1;
    43. }

    44. int InsertHead(List *lp, ElementType *pdata)
    45. {
    46.         ChainNode *newp = NULL;

    47.         if(!lp) return 0;

    48.         newp = NewChainNode(pdata);
    49.         if(!newp) return 0;

    50.         if(IsEmpty(lp))
    51.         {
    52.                 /* 为空则以此为首节点和尾节点 */
    53.                 lp->head = lp->tail = newp;
    54.                 lp->total++;
    55.         }
    56.         else
    57.         {
    58.                 /* 非空则以新节点为首节点 */
    59.                 (lp->head)->prev = newp;
    60.                 newp->next = lp->head;
    61.                 lp->head = newp;
    62.                 lp->total++;
    63.         }
    64.         return 1;
    65. }

    66. int InsertTail(List *lp, ElementType *pdata)
    67. {
    68.         ChainNode *newp = NULL;

    69.         if(!lp) return 0;

    70.         newp = NewChainNode(pdata);
    71.         if(!newp) return 0;

    72.         if(IsEmpty(lp))
    73.         {
    74.                 /* 为空则以此为首节点和尾节点 */
    75.                 lp->head = lp->tail = newp;
    76.                 lp->total++;
    77.         }
    78.         else
    79.         {
    80.                 /* 非空则将新节点接在后面 */
    81.                 (lp->tail)->next = newp;
    82.                 newp->prev = lp->tail;
    83.                 lp->tail = newp;
    84.                 lp->total++;
    85.         }
    86.         return 1;
    87. }

    88. int InsertNode(List *lp, int n, ElementType *pdata)
    89. {
    90.         ChainNode *p = NULL;
    91.         ChainNode *newp = NULL;

    92.         if(!lp) return 0;
    93.         if(n <= 1 || n > lp->total) return 0;

    94.         p = GetChainNode(lp, n - 1);
    95.         if(!p) return 0;

    96.         newp = NewChainNode(pdata);
    97.         if(!newp) return 0;

    98.         /* 插入点后的节点的prev指向新节点 */
    99.         (p->next)->prev = newp;

    100.         /* 新节点的next指向插入点后的节点 */
    101.         newp->next = p->next;

    102.         /* 新节点的prev指向插入点前的节点 */
    103.         newp->prev = p;

    104.         /* 插入点前的节点的next指向新节点 */
    105.         p->next = newp;

    106.         lp->total++;
    107.         return 1;
    108. }

    109. int RemoveNode(List *lp, int n)
    110. {
    111.         ChainNode *p = NULL;

    112.         if(!lp) return 0;
    113.         if(n < 1 || n > lp->total) return 0;

    114.         if(lp->total == 1)
    115.         {
    116.                 /* 只有一个节点则清除之 */
    117.                 free(lp->head);
    118.                 lp->head = NULL;
    119.                 lp->tail = NULL;
    120.                 lp->total = 0;
    121.         }
    122.         else
    123.         {
    124.                 if(n == 1)
    125.                 {
    126.                         /* 删除多节点的首节点,先保存第二节点 */
    127.                         p = (lp->head)->next;

    128.                         /* 删除首节点 */
    129.                         free(lp->head);

    130.                         /* 将第二节点设为首节点 */
    131.                         p->prev = NULL;
    132.                         lp->head = p;

    133.                         lp->total--;
    134.                 }
    135.                 else if(n == lp->total)
    136.                 {
    137.                         /* 删除多节点的尾节点,先保存倒数第二节点 */
    138.                         p = (lp->tail)->prev;

    139.                         /* 删除尾节点 */
    140.                         free(lp->tail);

    141.                         /* 将倒数第二节点设为尾节点 */
    142.                         p->next = NULL;
    143.                         lp->tail = p;

    144.                         lp->total--;
    145.                 }
    146.                 else
    147.                 {
    148.                         /* 删除多节点的中间节点,获取删除节点信息 */
    149.                         p = GetChainNode(lp, n);

    150.                         /* 删除点前一节点的next设为删除点后一节点 */
    151.                         (p->prev)->next = p->next;

    152.                         /* 删除点后一节点的prev设为删除点前一节点 */
    153.                         (p->next)->prev = p->prev;

    154.                         /* 删除节点 */
    155.                         free(p);

    156.                         lp->total--;
    157.                 }
    158.         }
    159.         return 1;
    160. }

    161. ChainNode * NewChainNode(ElementType *pdata)
    162. {
    163.         ChainNode *p = NULL;
    164.         p = (ChainNode *)malloc(sizeof(ChainNode));
    165.         if(!p) return p;
    166.         memcpy(&p->data, pdata, sizeof(ElementType));
    167.         p->prev = NULL;
    168.         p->next = NULL;
    169.         return p;
    170. }

    171. int IsEmpty(List *lp)
    172. {
    173.         return lp->total == 0;
    174. }

    175. ChainNode * GetChainNode(List *lp, int n)
    176. {
    177.         ChainNode *p = NULL;
    178.         int i = 0;

    179.         if(!lp) return 0;
    180.         if(n < 1 || n > lp->total) return 0;

    181.         for(i = 1, p = lp->head; i < n; i++, p = p->next);

    182.         return p;
    183. }

    184. int ListTraverse(List * lp, void (*pfn)(ElementType *pdata))
    185. {
    186.         ChainNode *p = NULL;
    187.         if(!lp) return 0;

    188.         for (p = lp->head; p; p = p->next)
    189.                 pfn(&p->data);
    190.         printf("\n");
    191.         return 1;
    192. }
    复制代码

    1. /* test2.c -- 单向链表      */
    2. /* 和list2.c一起编译        */


    3. #include "List2.h"

    4. void myprintf(ElementType * pdata)
    5. {
    6.         printf("%d ", *pdata);
    7. }

    8. int main()
    9. {
    10.         int i;
    11.         List *lp = ListInit();
    12.         ElementType a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    13.         ElementType data = 99;

    14.         if(!lp)
    15.         {
    16.                 printf("\nInitList error!\n");
    17.                 return 0;
    18.         }

    19.         for (i = 0; i < 10; i++)
    20.         {
    21.                 InsertTail(lp, a+i);
    22.         }

    23.         ListTraverse(lp, myprintf);

    24.         InsertHead(lp, &data);
    25.         ListTraverse(lp, myprintf);

    26.         InsertTail(lp, &data);
    27.         ListTraverse(lp, myprintf);

    28.         InsertNode(lp, 3, &data);
    29.         ListTraverse(lp, myprintf);

    30.         RemoveNode(lp, 3);
    31.         ListTraverse(lp, myprintf);

    32.         RemoveNode(lp, 12);
    33.         ListTraverse(lp, myprintf);

    34.         RemoveNode(lp, 1);
    35.         ListTraverse(lp, myprintf);

    36.         ListDestory(lp);
    37.         return 1;
    38. }
    复制代码
    QQ图片20150208111722.jpg
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2015-2-9 10:56:18 | 显示全部楼层

    赞!学编程非写代码,拍错误方可学会。Why,因为语法不是我们定义的,编译器不是我们实现的,所以必须要动手写代码才能学会编程。

    还有一种实现在这里:http://www.sicaril.com/thread-529-1-2.html
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表