当前位置:   article > 正文

【数据结构】链表(单链表实现+测试+原码)

【数据结构】链表(单链表实现+测试+原码)

1.链表


1.1 链表的概念及结构

概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表 中的指针链接次序实现的 。

现实中:链表就像是一列动车,一节连着一节
数据结构中的链表

 注意:
1.从上图可看出,链式结构在逻辑上是连续的。但是在物理上不一定连续

2.现实中的结点一般都是从堆上申请出来的

3.从堆上申请的空间,是按照一定的策略来分配的,两次申请的空间可能连续,也可能不连续

2  链表的实现

SList.h(头文件引用)

  1. #pragma once
  2. #define _CRT_SECURE_NO_WARNINGS 1
  3. #include <stdio.h>
  4. #include <malloc.h>
  5. #include <assert.h>
  6. typedef int SLTDataType;
  7. typedef struct SListNode
  8. {
  9. SLTDataType data;
  10. struct SListNode* next;
  11. }SLTNode;
  12. void SLTPrint(SLTNode* phead);
  13. SLTNode* BuySListNode(SLTDataType x);
  14. void SLTPushBack(SLTNode ** pphead,SLTDataType x);
  15. void SLTPushFront(SLTNode** pphead, SLTDataType x);
  16. void SLTPopBack(SLTNode** pphead);
  17. void SLTPopFront(SLTNode** pphead);
  18. //作业
  19. SLTNode* SLTFind(SLTNode* pphead,SLTDataType x);
  20. //在pos之前插入x
  21. void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
  22. //在之后插入x
  23. void SLTInsertAfter( SLTNode* pos, SLTDataType x);
  24. //删除pos位置
  25. void SLTErase(SLTNode** pphead, SLTNode* pos);
  26. //删除pos后一个位置
  27. void SLTEraseAfter(SLTNode* phead,SLTNode* pos);

SList.c(函数功能的实现)

  1. #include "SList.h"
  2. void SLTPrint(SLTNode* phead)
  3. {
  4. SLTNode* cur = phead;
  5. while (cur != NULL)
  6. {
  7. printf("%d->", cur->data);
  8. cur = cur->next;
  9. }
  10. printf("NULL\n");
  11. }
  12. SLTNode* BuySListNode(SLTDataType x)
  13. {
  14. SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
  15. if (newnode == NULL)
  16. {
  17. perror("malloc fail");
  18. exit(-1);
  19. }
  20. newnode->data = x;
  21. newnode->next = NULL;
  22. return newnode;
  23. }
  24. void SLTPushBack(SLTNode** pphead,SLTDataType x) //尾插
  25. //需要用二级指针,结构体指针(地址),传递实参
  26. {
  27. assert(pphead); //空地址不正确
  28. //assert(*pphead);//空链表可以尾插
  29. SLTNode* newnode = BuySListNode(x);
  30. if (*pphead == NULL) //如果为空,则指向新创建元素
  31. {
  32. *pphead = newnode;
  33. }
  34. else //不为空则遍历到尾部插入数据
  35. {
  36. //需要用指针结构体指针,改变结构体,传递形参
  37. SLTNode* tail = *pphead;
  38. while (tail->next != 0)
  39. {
  40. tail = tail->next;
  41. }
  42. tail->next = newnode;
  43. }
  44. }
  45. void SLTPushFront(SLTNode** pphead, SLTDataType x)//头插
  46. {
  47. assert(pphead); //空地址不正确
  48. assert(*pphead);//空链表不可以前删
  49. SLTNode* newnode = BuySListNode(x);
  50. newnode->next = *pphead;
  51. *pphead = newnode;
  52. }
  53. void SLTPopBack(SLTNode** pphead) //尾删
  54. {
  55. // 1.空
  56. assert(*pphead != NULL);
  57. // 2.一个节点
  58. if ((*pphead)->next == NULL)
  59. {
  60. free(*pphead);
  61. *pphead = NULL;
  62. }
  63. // 3.多个节点
  64. else
  65. {
  66. SLTNode* tail = *pphead;
  67. while (tail->next->next)
  68. {
  69. tail = tail->next;
  70. }
  71. free(tail->next);
  72. tail->next = NULL;
  73. }
  74. }
  75. void SLTPopFront(SLTNode** pphead) //头删
  76. {
  77. assert(pphead);
  78. assert(*pphead);
  79. SLTNode* newhead = (*pphead)->next;
  80. free(*pphead);
  81. *pphead = newhead;
  82. }
  83. SLTNode* SLTFind(SLTNode*phead, SLTDataType x)
  84. {
  85. assert(phead);
  86. SLTNode* tail = phead;
  87. while (tail)
  88. {
  89. if (tail->data == x)
  90. {
  91. return tail;
  92. }
  93. tail = tail->next;
  94. }
  95. return NULL;
  96. while (tail->data != x)
  97. {
  98. tail = tail->next;
  99. if (tail->next==NULL&&tail->data!=x)
  100. //下一个元素的值指向NULL并且数据值不等于要查找的数,既已遍历查找完毕并且没有找到数据
  101. {
  102. printf(" 输入错误,找不到输入值\n");
  103. return 0;
  104. }
  105. }
  106. printf("已找到:%d\n", x);
  107. return tail;
  108. }
  109. void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
  110. {
  111. //有错误版本 ,地址近似一样(bug)find函数调试就好了
  112. assert(pos);
  113. assert(*pphead);
  114. if (pos == *pphead)
  115. {
  116. SLTPushFront(pphead, x);
  117. }
  118. else
  119. {
  120. SLTNode* tail = *pphead;
  121. //在pos之前插入x
  122. while (tail->next != pos)
  123. {
  124. tail = tail->next;
  125. }
  126. SLTNode* newnode = BuySListNode(x);
  127. tail->next = newnode;
  128. newnode->next = pos;
  129. }
  130. }
  131. void SLTInsertAfter(SLTNode* pos, SLTDataType x)
  132. {
  133. assert(pos);
  134. assert(pos->next);
  135. SLTNode* newnode = BuySListNode(x);
  136. //注意顺序,不然会照成死循环(画图)
  137. newnode->next = pos->next;
  138. pos->next = newnode;
  139. }
  140. void SLTErase(SLTNode** pphead, SLTNode* pos)
  141. {
  142. assert(pos);
  143. if (pos == *pphead)
  144. {
  145. SLTPopFront(pphead);
  146. }
  147. else
  148. {
  149. SLTNode* prev = *pphead;
  150. while (prev->next != pos)
  151. {
  152. prev = prev->next;
  153. }
  154. prev->next = pos->next;
  155. free(pos);
  156. }
  157. }
  158. void SLTEraseAfter(SLTNode* phead,SLTNode* pos)
  159. {
  160. //assert(pos);
  161. //检查是否为尾节点
  162. //assert(pos->next);
  163. SLTNode* posNext; //纪录要删除的节点
  164. //避免丢失无法Free
  165. posNext = pos->next;
  166. //pos->next = pos->next->next;
  167. pos->next = posNext->next;
  168. free(posNext);
  169. posNext = NULL;
  170. }

Test_1_16(各种功能的调试、函数、以及面试OJ题的接口实现)

  1. #include "SList.h"
  2. void TestSList1()
  3. {
  4. int n;
  5. printf("请输入链表长度:");
  6. scanf("%d", &n);
  7. printf("\n请依次输入每个节点的值:");
  8. SLTNode* plist = NULL; //第一个元素的地址
  9. for (size_t i = 0; i < n; i++)
  10. {
  11. int val;
  12. scanf("%d", &val);
  13. SLTNode* newnode = BuySListNode(val);
  14. //头插
  15. newnode->next = plist;
  16. plist = newnode;
  17. }
  18. SLTPrint(plist);
  19. SLTPushBack(&plist, 5);
  20. SLTPrint(plist);
  21. }
  22. void TestSList()
  23. {
  24. SLTNode* plist = NULL;
  25. SLTPushBack(&plist, 1);
  26. SLTPushBack(&plist, 2);
  27. SLTPushBack(&plist, 3);
  28. SLTPushBack(&plist, 4);
  29. SLTPushBack(&plist, 5);
  30. SLTPrint(plist);
  31. SLTPushFront(&plist, 10);
  32. SLTPushFront(&plist, 20);
  33. SLTPushFront(&plist, 30);
  34. SLTPushFront(&plist, 40);
  35. SLTPrint(plist);
  36. }
  37. void TestSList3()
  38. {
  39. SLTNode* plist = NULL;
  40. SLTPushBack(&plist, 1);
  41. SLTPushBack(&plist, 2);
  42. SLTPushBack(&plist, 3);
  43. SLTPushBack(&plist, 4);
  44. SLTPushBack(&plist, 5);
  45. SLTPrint(plist);
  46. SLTPopBack(&plist);
  47. SLTPrint(plist);
  48. SLTPopBack(&plist);
  49. SLTPrint(plist);
  50. SLTPopBack(&plist);
  51. SLTPrint(plist);
  52. SLTPopBack(&plist);
  53. SLTPrint(plist);
  54. SLTPopBack(&plist);
  55. SLTPrint(plist);
  56. SLTPopBack(&plist);
  57. SLTPrint(plist);
  58. }
  59. void TestSList4()
  60. {
  61. SLTNode* plist = NULL;
  62. SLTPushBack(&plist, 1);
  63. SLTPushBack(&plist, 2);
  64. SLTPushBack(&plist, 3);
  65. SLTPushBack(&plist, 4);
  66. SLTPushBack(&plist, 5);
  67. SLTPrint(plist);
  68. //SLTPopFront(&plist);
  69. //SLTPopFront(&plist);
  70. //SLTPrint(plist);
  71. SLTFind(plist, 1);
  72. SLTFind(plist, 2);
  73. SLTFind(plist, 3);
  74. SLTFind(plist, 4);
  75. SLTFind(plist, 5);
  76. SLTFind(plist, 0);
  77. }
  78. void TestSlist5()
  79. {
  80. SLTNode* plist = NULL;
  81. SLTPushBack(&plist, 1);
  82. SLTPushBack(&plist, 2);
  83. SLTPushBack(&plist, 3);
  84. SLTPushBack(&plist, 4);
  85. SLTPushBack(&plist, 5);
  86. SLTPrint(plist);
  87. SLTNode* pos = SLTFind(plist,4);
  88. if (pos)
  89. pos->data = 20;
  90. //在pos之前插入x
  91. //SLTInsert(&plist, pos, 5);
  92. SLTPrint(plist);
  93. }
  94. void TestSlist6()
  95. {
  96. SLTNode* plist = NULL;
  97. SLTPushBack(&plist, 1);
  98. SLTPushBack(&plist, 2);
  99. SLTPushBack(&plist, 3);
  100. SLTPushBack(&plist, 4);
  101. SLTPushBack(&plist, 5);
  102. SLTPrint(plist);
  103. SLTNode* pos = SLTFind(plist, 4);
  104. SLTInsert(&plist, pos, 90);
  105. SLTPrint(plist);
  106. }
  107. void TestSlist7()
  108. {
  109. SLTNode* plist = NULL;
  110. SLTPushBack(&plist, 1);
  111. SLTPushBack(&plist, 2);
  112. SLTPushBack(&plist, 3);
  113. SLTPushBack(&plist, 4);
  114. SLTPushBack(&plist, 5);
  115. SLTPrint(plist);
  116. SLTNode* pos = SLTFind(plist, 4);
  117. SLTInsertAfter(pos, 90);
  118. SLTPrint(plist);
  119. }
  120. void TestSlist8()
  121. {
  122. SLTNode* plist = NULL;
  123. SLTPushBack(&plist, 1);
  124. SLTPushBack(&plist, 2);
  125. SLTPushBack(&plist, 3);
  126. SLTPushBack(&plist, 4);
  127. SLTPushBack(&plist, 5);
  128. SLTPrint(plist);
  129. SLTNode* pos = SLTFind(plist, 4);
  130. SLTErase(&plist,pos);
  131. SLTPrint(plist);
  132. }
  133. void TestSlist9()
  134. {
  135. SLTNode* plist = NULL;
  136. SLTPushBack(&plist, 1);
  137. SLTPushBack(&plist, 2);
  138. SLTPushBack(&plist, 3);
  139. SLTPushBack(&plist, 4);
  140. SLTPushBack(&plist, 5);
  141. SLTPrint(plist);
  142. SLTNode* pos = SLTFind(plist, 4);
  143. SLTEraseAfter(&plist, pos);
  144. SLTPrint(plist);
  145. }
  146. struct SListNode* removeElement()
  147. {
  148. ;
  149. }
  150. struct ListNode {
  151. int val;
  152. struct ListNode* next;
  153. };
  154. //
  155. //struct ListNode* FindKthToTail(struct ListNode* pListHead, int k)
  156. //{
  157. // struct ListNode* first = pListHead;
  158. // struct ListNode* tail = pListHead;
  159. //
  160. // while (first->next)
  161. // {
  162. // while (k>0&&first->next)
  163. // {
  164. // k--;
  165. // first = first->next;
  166. // }
  167. // if (first->next==NULL)
  168. // {
  169. // return tail;
  170. // }
  171. // tail = tail->next;
  172. // first = first->next;
  173. // }
  174. // //tail=tail->next;
  175. // return tail->next;
  176. //}
  177. struct ListNode* FindKthToTail(struct ListNode* pListHead, int k)
  178. {
  179. if (pListHead == NULL)
  180. {
  181. return pListHead;
  182. }
  183. struct ListNode* first = pListHead;
  184. struct ListNode* tail = pListHead;
  185. while (first->next)
  186. {
  187. while (k > 0 && first->next)
  188. {
  189. k--;
  190. first = first->next;
  191. //if (first->next == NULL && k > 0)
  192. //{
  193. // return NULL;
  194. //}
  195. }
  196. if (first->next == NULL&&k==1)
  197. {
  198. return tail;
  199. }
  200. else
  201. {
  202. return NULL;
  203. }
  204. tail = tail->next;
  205. first = first->next;
  206. }
  207. //tail=tail->next;
  208. return tail->next;
  209. }
  210. int main()
  211. {
  212. struct SListNode* n1 = (struct ListNode*)malloc(sizeof(struct SListNode));
  213. struct SListNode* n2 = (struct ListNode*)malloc(sizeof(struct SListNode));
  214. struct SListNode* n3 = (struct ListNode*)malloc(sizeof(struct SListNode));
  215. struct SListNode* n4 = (struct ListNode*)malloc(sizeof(struct SListNode));
  216. struct SListNode* n5 = (struct ListNode*)malloc(sizeof(struct SListNode));
  217. n1->data = 1;
  218. n2->data = 2;
  219. n3->data = 3;
  220. n4->data = 4;
  221. n5->data = 5;
  222. n1->next = n2;
  223. n2->next = n3;
  224. n3->next = n4;
  225. n4->next = n5;
  226. n5->next = NULL;
  227. FindKthToTail(n1, 6);
  228. //TestSList1();
  229. //TestSList3();
  230. //TestSlist5();
  231. //TestSlist7();
  232. //TestSlist8();
  233. //TestSlist9();
  234. /*struct SListNode* n1 = (struct ListNode*)malloc(sizeof(struct SListNode));
  235. struct SListNode* n2 = (struct ListNode*)malloc(sizeof(struct SListNode));
  236. struct SListNode* n3 = (struct ListNode*)malloc(sizeof(struct SListNode));
  237. struct SListNode* n4 = (struct ListNode*)malloc(sizeof(struct SListNode));
  238. n1->data = 7;
  239. n2->data = 7;
  240. n3->data = 7;
  241. n4->data = 7;
  242. n1->next = n2;
  243. n2->next = n3;
  244. n3->next = n4;
  245. n4->next = NULL;
  246. struct SListNode* head = removeElement(n1, 7);
  247. return 0;*/
  248. }
  249. //
  250. //
  251. //
  252. //
  253. //int nums1[6] = { 1,2,3,0,0,0 };
  254. //int nums1Size = 6;
  255. //int m = 3;
  256. //int nums2[3] = { 2,5,6 };
  257. //int nums2Size = 3;
  258. //int n = 3;
  259. int nums1[1];
  260. int m = 0;
  261. int nums2[1] = {1};
  262. int n = 1;
  263. // int p1 = m - 1, p2 = n - 1;
  264. // int tail = m + n - 1;
  265. // int cur;
  266. // while (p1 > -1 || p2 > -1)
  267. // {
  268. // if (p1 == -1)
  269. // {
  270. // cur = nums2[p2--];
  271. // }
  272. // else if (p2 == -1)
  273. // {
  274. // cur = nums1[p1--];
  275. // }
  276. // else if (nums1[p1] > nums2[p2])
  277. // {
  278. // cur = nums1[p1--];
  279. // }
  280. // else
  281. // {
  282. // cur = nums2[p2--];
  283. // }
  284. // nums1[tail--] = cur;
  285. // }

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

闽ICP备14008679号