当前位置:   article > 正文

数据结构之单链表

数据结构之单链表

目录

一、单链表

1.1 什么是单链表

1.2 单链表的特点

1.3 单链表与顺序表的区别

二、C语言实现

2.1 SList.h

2.2 SList.c


一、单链表

1.1 什么是单链表

        单链表是一种常见的数据结构,用于存储一系列元素,这些元素按照线性顺序排列,并且每个元素都包含一个指向下一个元素的指针(称为“next”指针)。单链表由一系列节点组成,每个节点包含两部分信息:数据域和指针域。数据域存储节点所包含的数据,而指针域则存储指向下一个节点的指针。

  1. struct SListNode
  2. {
  3. int data; // 节点数据
  4. struct SListNode* next; // 下⼀个节点的地址
  5. };

1.2 单链表的特点

  • 每个节点都包含指向下一个节点的指针,最后一个节点的指针为空(NULL)。
  • 可以在链表的任何位置插入或删除元素,而不需要移动其他元素,只需修改相应节点的指针即可。
  • 链表的插入和删除操作的时间复杂度为O(1),在链表中查找特定元素的时间复杂度为O(n),其中n是链表的长度。

1.3 单链表与顺序表的区别

  1. 由于单链表的节点通过指针连接,因此它不需要连续的内存空间,这使得它在插入和删除操作方面比数组更加灵活
  2. 然而,由于无法直接访问链表中的任意位置元素,因此在需要随机访问元素的情况下,单链表的效率可能不如数组。

二、C语言实现

难点:对单链表的操作本质上是对结构体指针的操作。根据前面指针的相关知识以及对比顺序表的操作,不难发现:凡是涉及到对链表的修改操作时,需要传址调用函数。在链表中也就是传指针的地址,所以参数为二级指针

2.1 SList.h

  1. #pragma once
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<assert.h>
  5. typedef int SLTDataType;
  6. typedef struct SlistNode
  7. {
  8. SLTDataType data;
  9. struct SlistNode* next;
  10. }SLTNode;
  11. //链表打印
  12. void SLTPrint(SLTNode* phead);
  13. //链表销毁
  14. void SLTDestory(SLTNode** pphead);
  15. // 头插
  16. void SLTPushFront(SLTNode** pphead, SLTDataType x);
  17. // 尾插
  18. void SLTPushBack(SLTNode** pphead, SLTDataType x);
  19. // 头删
  20. void SLTPopFront(SLTNode** pphead);
  21. // 尾删
  22. void SLTPopBack(SLTNode** pphead);
  23. // 查找
  24. SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
  25. // 在指定位置之前插⼊数据
  26. void SLTInsertBefore(SLTNode** pphead, SLTNode* pos, SLTDataType x);
  27. // 在指定位置之后插入数据
  28. void SLTInsertAfter(SLTNode* pos, SLTDataType x);
  29. // 删除指定位置的节点
  30. void SLTDelete(SLTNode** pphead, SLTNode* pos);

2.2 SList.c

  1. #include"SList.h"
  2. //单链表的打印
  3. void SLTPrint(SLTNode* phead)
  4. {
  5. SLTNode* pcur = phead;
  6. while (pcur)
  7. {
  8. printf("%d->", pcur->data);
  9. pcur = pcur->next;
  10. }
  11. printf("NULL\n");
  12. }
  13. //将动态开辟空间的重复操作单独封装
  14. SLTNode* SLTBuyNode(SLTDataType x)
  15. {
  16. SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
  17. if (newnode == NULL)
  18. {
  19. perror("malloc");
  20. exit(1);
  21. }
  22. newnode->data = x;
  23. newnode->next = NULL;
  24. return newnode;
  25. }
  26. // 尾插
  27. void SLTPushBack(SLTNode** pphead, SLTDataType x)
  28. {
  29. assert(pphead);
  30. SLTNode* newnode = SLTBuyNode(x);
  31. //判断是否为空节点
  32. if (*pphead == NULL)
  33. {
  34. *pphead = newnode;
  35. }
  36. else
  37. {
  38. //找尾节点
  39. SLTNode* ptail = *pphead;
  40. while (ptail->next)
  41. {
  42. ptail = ptail->next;
  43. }
  44. ptail->next = newnode;
  45. }
  46. }
  47. //头插
  48. void SLTPushFront(SLTNode** pphead, SLTDataType x)
  49. {
  50. assert(pphead);
  51. SLTNode* newnode = SLTBuyNode(x);
  52. newnode->next = *pphead;
  53. *pphead = newnode;
  54. }
  55. //尾删
  56. void SLTPopBack(SLTNode** pphead)
  57. {
  58. assert(pphead);
  59. assert(*pphead);
  60. //链表只有一个节点
  61. if ((*pphead)->next == NULL)
  62. {
  63. free(*pphead);
  64. *pphead = NULL;
  65. }
  66. else
  67. {
  68. //找尾节点
  69. SLTNode* ptail = *pphead;
  70. SLTNode* prev = *pphead;
  71. while (ptail->next)
  72. {
  73. prev = ptail;
  74. ptail = ptail->next;
  75. }
  76. free(ptail);
  77. ptail = NULL;
  78. prev->next = NULL;
  79. }
  80. }
  81. //头删
  82. void SLTPopFront(SLTNode** pphead)
  83. {
  84. assert(pphead);
  85. assert(*pphead);
  86. //链表只有一个节点
  87. if ((*pphead)->next == NULL)
  88. {
  89. free(*pphead);
  90. *pphead = NULL;
  91. }
  92. else
  93. {
  94. SLTNode* phead = *pphead;
  95. *pphead = (*pphead)->next;
  96. free(phead);
  97. }
  98. }
  99. // 查找
  100. SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
  101. {
  102. assert(phead);
  103. SLTNode* pcur = phead; //不修改原指针指向
  104. while (pcur)
  105. {
  106. if (phead->data == x)
  107. {
  108. return pcur;
  109. }
  110. pcur = phead->next;
  111. }
  112. return NULL;
  113. }
  114. // 在指定位置之前插⼊数据
  115. void SLTInsertBefore(SLTNode** pphead, SLTNode* pos, SLTDataType x)
  116. {
  117. assert(pphead && *pphead);
  118. assert(pos);
  119. SLTNode* newnode = SLTBuyNode(x);
  120. SLTNode* prev = *pphead;
  121. //判断是否为头插
  122. if (pos == *pphead)
  123. {
  124. SLTPushFront(pphead, x);
  125. }
  126. else
  127. {
  128. //找到前一个结点
  129. while (prev->next != pos)
  130. {
  131. prev = prev->next;
  132. }
  133. //重新连接
  134. prev->next = newnode;
  135. newnode->next = pos;
  136. }
  137. }
  138. // 在指定位置之后插⼊数据
  139. void SLTInsertAfter(SLTNode* pos, SLTDataType x)
  140. {
  141. assert(pos);
  142. SLTNode* newnode = SLTBuyNode(x);
  143. newnode = pos->next;
  144. pos->next = newnode;
  145. }
  146. // 删除指定位置的节点
  147. void SLTDelete(SLTNode** pphead, SLTNode* pos)
  148. {
  149. assert(pphead && *pphead);
  150. assert(pos);
  151. SLTNode* prev = *pphead;
  152. if (*pphead == pos) //如果是头节点
  153. {
  154. SLTPopFront(pphead);
  155. }
  156. else
  157. {
  158. //寻找前一个节点
  159. while (prev->next != pos)
  160. {
  161. prev = prev->next;
  162. }
  163. prev->next = pos->next;
  164. free(pos);
  165. pos = NULL;
  166. }
  167. }
  168. //链表销毁
  169. void SLTDestory(SLTNode** pphead)
  170. {
  171. assert(pphead);
  172. SLTNode* pcur = *pphead;
  173. while (pcur)
  174. {
  175. SLTNode* temp = pcur->next;
  176. free(pcur);
  177. pcur = temp;
  178. }
  179. *pphead = NULL;
  180. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/436198
推荐阅读
相关标签
  

闽ICP备14008679号