当前位置:   article > 正文

【数据结构】 链表_链表需要先清空在销毁吗

链表需要先清空在销毁吗

链表的概念及结构

概念:基于数组的缺点,数据结构中诞生了新的结构就是 链表

当一组数据需要频繁的进行插入、删除操作时候,链表则是首选的数据结构

链表也属于 线性表

链表的组成

链表由结点组成

结点分为两部分:

  • 数据域,保存存储的数据元素

  • 指针域,指向下一个结点的地址

注:链表也属于线性表,拥有线性表的所有特点

结点的创建:

  1. struct Node{
  2.     int data;    //数据域
  3.     struct Node *next;    //指针域
  4. };

结点结构体示意图:

实现单向链表,能够存放整型数据,设计需求如下:

设计需求:
  1. 链表的初始化

  1. 获取链表长度

  1. 插入指定位置结点

  1. 遍历链表

  1. 删除指定位置结点

  1. 清空链表

  1. 释放链表

链表的初始化

链表初始化 核心代码:
  1. typedef struct node
  2. {
  3. int data;//数据域
  4. struct node* next; //指针域
  5. }Node, *LinkList; //Node是struct node的别名, LinkList 代表struct node*数据类型
  6. //链表的初始化
  7. LinkList creat_list()
  8. {
  9. LinkList head = (Node *)malloc(sizeof(Node));
  10. if (!head)
  11. {
  12. printf("内存分配失败\n");
  13. return NULL;
  14. }
  15. head->next = NULL; //带头结点的链表,只维护指针域,无需维护数据域
  16. return head;
  17. }

功能:

创建一个链表的头结点,并返回给使用者

链表长度获取

链表统计 核心代码:
  1. //统计链表长度
  2. int size_list(LinkList head)
  3. {
  4. if (head == NULL)
  5. {
  6. printf("传入链表为空\n");
  7. return 0;
  8. }
  9. Node * pCur = head->next; //获取第一个有数据的结点
  10. int num = 0;
  11. while (pCur != NULL)
  12. {
  13. num++;
  14. pCur = pCur->next;
  15. }
  16. return num;
  17. }

功能:

统计链表中结点的个数并返回

链表的插入

链表插入 核心代码:
  1. //插入结点 参数1 链表的头结点 参数2 插入位置 参数3 插入数据
  2. void insert_list(LinkList head, int pos , int val)
  3. {
  4. if (head == NULL)
  5. {
  6. printf("传入链表为空\n");
  7. return;
  8. }
  9. if (pos < 0 || pos > size_list(head))
  10. {
  11. printf("插入位置无效\n");
  12. return;
  13. }
  14. //辅助指针,帮助我们找到待插入位置的前驱结点
  15. Node* pCur = head;
  16. for (int i = 0; i < pos; i++)
  17. {
  18. pCur = pCur->next;
  19. }
  20. //创建新结点
  21. Node* newNode = (Node *)malloc(sizeof( Node));
  22. if (!newNode)
  23. {
  24. return;
  25. }
  26. newNode->data = val;
  27. newNode->next = NULL;
  28. //将新结点插入到链表长
  29. newNode->next = pCur->next;
  30. pCur->next = newNode;
  31. }

功能:

向指定的位置上,插入新的结点

链表的遍历

链表遍历 核心代码:
  1. //遍历链表
  2. void foreach_list(LinkList head)
  3. {
  4. if (head == NULL)
  5. {
  6. printf("传入链表为空\n");
  7. return;
  8. }
  9. Node* pCur = head->next; //拿到第一个有数据的结点
  10. while (pCur != NULL)
  11. {
  12. printf("%d ", pCur->data);
  13. pCur = pCur->next;
  14. }
  15. printf("\n");
  16. }

功能:

打印链表中每个结点的数据域

链表的删除

链表删除 核心代码:
  1. //删除结点 参数1 链表表头 参数2 删除位置
  2. void delete_list(LinkList head, int pos)
  3. {
  4. if (head == NULL)
  5. {
  6. printf("传入链表为空\n");
  7. return;
  8. }
  9. if (pos < 0 || pos > size_list(head) - 1)
  10. {
  11. printf("删除位置无效\n");
  12. return;
  13. }
  14. //辅助指针,帮助我们找到待删除位置的前驱结点
  15. Node* pCur = head;
  16. for (int i = 0; i < pos; i++)
  17. {
  18. pCur = pCur->next;
  19. }
  20. //记录待删除结点
  21. Node* pDel = pCur->next;
  22. //更改指针,删除结点
  23. pCur->next = pDel->next;
  24. //释放待删除的结点
  25. free(pDel);
  26. }

功能:

删除指定位置上的结点

链表的清空

链表清空 核心代码:
  1. //清空链表
  2. void clear_list(LinkList head)
  3. {
  4. if (head == NULL)
  5. {
  6. printf("传入链表为空\n");
  7. return;
  8. }
  9. //指向第一个有数据的结点
  10. Node * pCur = head->next;
  11. while (pCur != NULL)
  12. {
  13. //先保存住下一个节点的位置
  14. Node * pNext = pCur->next;
  15. //释放节点
  16. free(pCur);
  17. pCur = pNext;
  18. }
  19. head->next = NULL;
  20. }

功能:

删除指定位置上的结点

链表的销毁

链表清空 核心代码:
  1. //销毁链表
  2. void destroy_list(LinkList head)
  3. {
  4. if (head == NULL)
  5. {
  6. printf("传入链表为空\n");
  7. return;
  8. }
  9. //先清空链表
  10. clear_list(head);
  11. //将头结点也释放掉,完成整个链表的销毁
  12. free(head);
  13. head = NULL;
  14. }

功能:

删除指定位置上的结点

完整代码:

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include<stdio.h>
  3. #include<string.h>
  4. #include<stdlib.h>
  5. typedef struct node
  6. {
  7. int data;//数据域
  8. struct node* next; //指针域
  9. }Node, *LinkList; //Node是struct node的别名, LinkList 代表struct node*数据类型
  10. //链表的初始化
  11. LinkList creat_list()
  12. {
  13. LinkList head = (Node *)malloc(sizeof(Node));
  14. if (!head)
  15. {
  16. printf("内存分配失败\n");
  17. return NULL;
  18. }
  19. head->next = NULL; //带头结点的链表,只维护指针域,无需维护数据域
  20. return head;
  21. }
  22. //统计链表长度
  23. int size_list(LinkList head)
  24. {
  25. if (head == NULL)
  26. {
  27. printf("传入链表为空\n");
  28. return 0;
  29. }
  30. Node * pCur = head->next; //获取第一个有数据的结点
  31. int num = 0;
  32. while (pCur != NULL)
  33. {
  34. num++;
  35. pCur = pCur->next;
  36. }
  37. return num;
  38. }
  39. //插入结点 参数1 链表的头结点 参数2 插入位置 参数3 插入数据
  40. void insert_list(LinkList head, int pos , int val)
  41. {
  42. if (head == NULL)
  43. {
  44. printf("传入链表为空\n");
  45. return;
  46. }
  47. if (pos < 0 || pos > size_list(head))
  48. {
  49. printf("插入位置无效\n");
  50. return;
  51. }
  52. //辅助指针,帮助我们找到待插入位置的前驱结点
  53. Node* pCur = head;
  54. for (int i = 0; i < pos; i++)
  55. {
  56. pCur = pCur->next;
  57. }
  58. //创建新结点
  59. Node* newNode = (Node *)malloc(sizeof( Node));
  60. if (!newNode)
  61. {
  62. return;
  63. }
  64. newNode->data = val;
  65. newNode->next = NULL;
  66. //将新结点插入到链表长
  67. newNode->next = pCur->next;
  68. pCur->next = newNode;
  69. }
  70. //遍历链表
  71. void foreach_list(LinkList head)
  72. {
  73. if (head == NULL)
  74. {
  75. printf("传入链表为空\n");
  76. return;
  77. }
  78. Node* pCur = head->next; //拿到第一个有数据的结点
  79. while (pCur != NULL)
  80. {
  81. printf("%d ", pCur->data);
  82. pCur = pCur->next;
  83. }
  84. printf("\n");
  85. }
  86. //删除结点 参数1 链表表头 参数2 删除位置
  87. void delete_list(LinkList head, int pos)
  88. {
  89. if (head == NULL)
  90. {
  91. printf("传入链表为空\n");
  92. return;
  93. }
  94. if (pos < 0 || pos > size_list(head) - 1)
  95. {
  96. printf("删除位置无效\n");
  97. return;
  98. }
  99. //辅助指针,帮助我们找到待删除位置的前驱结点
  100. Node* pCur = head;
  101. for (int i = 0; i < pos; i++)
  102. {
  103. pCur = pCur->next;
  104. }
  105. //记录待删除结点
  106. Node* pDel = pCur->next;
  107. //更改指针,删除结点
  108. pCur->next = pDel->next;
  109. //释放待删除的结点
  110. free(pDel);
  111. }
  112. //清空链表
  113. void clear_list(LinkList head)
  114. {
  115. if (head == NULL)
  116. {
  117. printf("传入链表为空\n");
  118. return;
  119. }
  120. //指向第一个有数据的结点
  121. Node * pCur = head->next;
  122. while (pCur != NULL)
  123. {
  124. //先保存住下一个节点的位置
  125. Node * pNext = pCur->next;
  126. //释放节点
  127. free(pCur);
  128. pCur = pNext;
  129. }
  130. head->next = NULL;
  131. }
  132. //销毁链表
  133. void destroy_list(LinkList head)
  134. {
  135. if (head == NULL)
  136. {
  137. printf("传入链表为空\n");
  138. return;
  139. }
  140. //先清空链表
  141. clear_list(head);
  142. //将头结点也释放掉,完成整个链表的销毁
  143. free(head);
  144. head = NULL;
  145. }
  146. int main() {
  147. LinkList head = creat_list(); //创建链表,获取表头
  148. //打印链表长度
  149. printf("链表长度为:%d\n", size_list(head));
  150. //插入结点
  151. insert_list(head, 0, 10);
  152. insert_list(head, 0, 20);
  153. insert_list(head, 1, 30);
  154. insert_list(head, 0, 40);
  155. //遍历链表
  156. printf("插入结点后,遍历结果为:\n"); // 40 20 30 10
  157. foreach_list(head);
  158. //打印链表长度
  159. printf("链表长度为:%d\n", size_list(head));
  160. //删除结点
  161. delete_list(head, 2);
  162. printf("删除结点后,遍历结果为:\n"); // 40 20 10
  163. foreach_list(head);
  164. //清空链表
  165. clear_list(head);
  166. printf("清空链表后,遍历结果为:\n");
  167. foreach_list(head);
  168. //销毁链表
  169. destroy_list(head);
  170. system("pause");
  171. return EXIT_SUCCESS;
  172. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/777273
推荐阅读
相关标签
  

闽ICP备14008679号