• C理解(四):链表


    本文主要探讨单链表与双链表相关知识。

    linux内核链表(include/linux/list.h)
            内核链表中纯链表封装,纯链表的各种操作函数(节点创建、插入、删除、遍历······),纯链表内嵌在驱动结构体中,实现驱动的创建、插入、删除、遍历等

    单链表 

            单链表链表头插入节点,尾插入节点,删除节点,逆序

    代码示例:

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. struct node
    4. {
    5. int data;
    6. struct node *next;
    7. };
    8. //创建节点
    9. struct node * create_node(int data)
    10. {
    11. struct node *p = (struct node *)malloc(sizeof(struct node));
    12. if(p == NULL)
    13. {
    14. printf("malloc error\n");
    15. return NULL;
    16. }
    17. p->data = data;
    18. p->next = NULL;
    19. return p;
    20. }
    21. //头部插入节点
    22. void insert_head(struct node *phead,struct node *new)
    23. {
    24. struct node *p = phead;
    25. if(p == NULL)
    26. exit(0);
    27. new->next = p->next;
    28. p->next = new;
    29. (phead->data)++; //头节点存储节点数量
    30. }
    31. //尾部插入
    32. void insert_tail(struct node *phead,struct node *new)
    33. {
    34. struct node *p = phead;
    35. if(p == NULL)
    36. exit(0);
    37. while(p->next != NULL)
    38. {
    39. p = p->next;
    40. }
    41. p->next = new;
    42. (phead->data)++; //头节点存储节点数量
    43. }
    44. //遍历链表
    45. void printf_link(struct node *phead)
    46. {
    47. if(phead == NULL)
    48. exit(0);
    49. struct node *p = phead;
    50. printf("num of struct : %d \n",p->data);
    51. while(p->next != NULL)
    52. {
    53. p = p->next;
    54. printf("struct data : %d\n",p->data);
    55. }
    56. }
    57. //删除节点
    58. int delete_node(struct node *phead,int data)
    59. {
    60. if(phead == NULL)
    61. exit(-1);
    62. struct node *p = phead;
    63. struct node *prev = NULL;
    64. while(p->next != NULL)
    65. {
    66. prev = p;
    67. p = p->next;
    68. if(p->data == data)
    69. {
    70. if(p->next != NULL)
    71. {
    72. prev->next = p->next; //其他节点
    73. free(p);
    74. }
    75. else
    76. {
    77. prev->next = NULL; //尾节点
    78. free(p);
    79. }
    80. (phead->data)--;
    81. return 0;
    82. }
    83. }
    84. printf("have no data\n");
    85. return -1;
    86. }
    87. //链表逆序
    88. void reserve_link(struct node *phead)
    89. {
    90. if(phead == NULL)
    91. exit(-1);
    92. struct node *p = phead->next;
    93. struct node *back = NULL;
    94. struct node *prev = NULL;
    95. if(p->next == NULL || p == NULL) //只有一个节点,不逆序
    96. return ;
    97. while(p->next != NULL) //两个及两个以上节点
    98. {
    99. back = p->next; //保存链表的下一个节点,由于头插逆序法插入节点与后面节点断开
    100. if(p == phead->next) //第一个节点指向NULL作为逆序首节点
    101. {
    102. p->next = NULL;
    103. }
    104. else
    105. {
    106. p->next = phead->next;
    107. }
    108. phead->next = p;
    109. p = back;
    110. }
    111. insert_head(phead,p); //最后一个节点插入到链表,由于最后一个节点指向NULL,while判断失效
    112. (phead->data)--; //头插最后一个节点时,默认新增一个节点
    113. }
    114. int main()
    115. {
    116. //创建头节点
    117. struct node *head = create_node(0);
    118. //头部插入节点
    119. insert_head(head,create_node(1));
    120. insert_head(head,create_node(2));
    121. insert_head(head,create_node(3));
    122. insert_head(head,create_node(4));
    123. insert_head(head,create_node(5));
    124. //尾部插入节点
    125. insert_tail(head,create_node(1));
    126. insert_tail(head,create_node(2));
    127. insert_tail(head,create_node(3));
    128. insert_tail(head,create_node(4));
    129. insert_tail(head,create_node(5));
    130. //遍历节点
    131. printf_link(head);
    132. //删除节点
    133. delete_node(head,5);
    134. delete_node(head,5);
    135. delete_node(head,4);
    136. //遍历节点
    137. printf_link(head);
    138. //链表逆序
    139. reserve_link(head);
    140. //遍历节点
    141. printf_link(head);
    142. return 0;
    143. }

    结果示例:

    双链表

            双链表尾插入,头插入,删除节点,前向遍历,后向遍历 

    代码示例:

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. struct node
    4. {
    5. int data;
    6. struct node *next;
    7. struct node *prev;
    8. };
    9. //创建节点
    10. struct node * create_node(int data)
    11. {
    12. struct node *p = (struct node *)malloc(sizeof(struct node));
    13. if(p == NULL)
    14. {
    15. printf("malloc error\n");
    16. return NULL;
    17. }
    18. p->data = data;
    19. p->next = NULL;
    20. p->prev = NULL;
    21. return p;
    22. }
    23. //头部插入节点
    24. void insert_head(struct node *phead,struct node *new)
    25. {
    26. struct node *p = phead;
    27. if(p == NULL)
    28. exit(0);
    29. new->next = p->next;
    30. if(p->next != NULL)
    31. p->next->prev = new;
    32. p->next = new;
    33. new->prev = p;
    34. (phead->data)++; //头节点存储节点数量
    35. }
    36. //尾部插入
    37. void insert_tail(struct node *phead,struct node *new)
    38. {
    39. struct node *p = phead;
    40. if(p == NULL)
    41. exit(0);
    42. while(p->next != NULL)
    43. {
    44. p = p->next;
    45. }
    46. p->next = new;
    47. new->prev = p;
    48. new->next = NULL;
    49. (phead->data)++; //头节点存储节点数量
    50. }
    51. //后项遍历链表
    52. void next_printf_link(struct node *phead)
    53. {
    54. if(phead == NULL)
    55. exit(0);
    56. struct node *p = phead;
    57. printf("num of struct : %d \n",p->data);
    58. while(p->next != NULL)
    59. {
    60. p = p->next;
    61. printf("struct data : %d\n",p->data);
    62. }
    63. }
    64. //前项遍历链表
    65. void prev_printf_link(struct node *phead)
    66. {
    67. if(phead == NULL)
    68. exit(0);
    69. struct node *p = phead;
    70. printf("num of struct : %d \n",p->data);
    71. while(p->next != NULL)
    72. {
    73. p = p->next;
    74. }
    75. while(p->prev != NULL)
    76. {
    77. printf("struct data : %d\n",p->data);
    78. p = p->prev;
    79. }
    80. }
    81. //删除节点
    82. int delete_node(struct node *phead,int data)
    83. {
    84. if(phead == NULL)
    85. exit(-1);
    86. struct node *p = phead;
    87. struct node *test = NULL;
    88. while(p->next != NULL)
    89. {
    90. p = p->next;
    91. if(p->data == data)
    92. {
    93. if(p->next == NULL)
    94. {
    95. p->prev->next = NULL; //尾节点
    96. }
    97. else
    98. {
    99. //其他节点
    100. p->prev->next = p->next;
    101. p->next->prev = p->prev;
    102. }
    103. free(p);
    104. (phead->data)--;
    105. return 0;
    106. }
    107. }
    108. printf("have no data\n");
    109. return -1;
    110. }
    111. int main()
    112. {
    113. //创建头节点
    114. struct node *head = create_node(0);
    115. //头部插入节点
    116. insert_head(head,create_node(1));
    117. insert_head(head,create_node(2));
    118. insert_head(head,create_node(3));
    119. insert_head(head,create_node(4));
    120. insert_head(head,create_node(5));
    121. //尾部插入节点
    122. insert_tail(head,create_node(1));
    123. insert_tail(head,create_node(2));
    124. insert_tail(head,create_node(3));
    125. insert_tail(head,create_node(4));
    126. insert_tail(head,create_node(5));
    127. //遍历节点
    128. next_printf_link(head);
    129. //删除节点
    130. delete_node(head,2);
    131. delete_node(head,5);
    132. delete_node(head,4);
    133. //next遍历节点
    134. next_printf_link(head);
    135. //prev遍历节点
    136. prev_printf_link(head);
    137. return 0;
    138. }

    结果示例:

  • 相关阅读:
    ChatGPT突然上线APP!iPhone可用、速度更快,GPT-4用量限制疑似取消
    TikTok对文化艺术的影响:传统与现代的碰撞
    linux进阶55——service文件
    李m圆申论
    Vue2.0+Vue3.0复习
    企业级软件开发流程
    微信小程序隐藏滚动条的方法
    码农的转型之路-偶遇大佬情况或有变
    精选20个大模型高频面试题
    Windows 内网渗透之委派攻击
  • 原文地址:https://blog.csdn.net/tyro_wzp/article/details/133419655