当前位置:   article > 正文

【数据结构初阶】单链表

【数据结构初阶】单链表

各位读者老爷好,鼠鼠我又来了哈。鼠鼠我呀现在来基于C语言实现一下单链表,希望对你有所帮助!

目录

1.链表的概念及结构

2.链表的分类

3.无头单向非循环链表的实现

3.1.单链表打印 

3.2.单链表尾插

3.3.单链表头插

3.4.单链表尾删

3.5.单链表头删

3.6.单链表查找

3.7.单链表在pos位置之和插入值

3.8.单链表删除pos位置之后的值 

3.9.在pos的前面插入值

3.10.删除pos位置的值

3.11.销毁单链表

4.单链表的小应用

4.1.slist.h

4.2.slist.c

4.3.test.c

5.ending 

鼠鼠我上次浅谈了顺序表。但是吧,Any coin has two sides。

顺序表有一些缺陷:

1.尾部插入效率还不错。头部或者中间插入删除,需要挪动数据,效率低下。

2.顺序表满了以后只能扩容。扩容是有一定消耗的,扩容一般是存在一定的空间浪费:一次扩得越多,可能浪费越多;一次扩得少,可能需要频繁扩容。

当然,顺序表也有它的优势:

得益于它的物理空间连续,顺序表支持随机的下标访问。 

So,我们有链表(也是线性表)可以避免顺序表的缺陷,那我们先来看看链表哈!

1.链表的概念及结构

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

不带头非循环单向链表的逻辑结构如下图:



 

链表是由节点(或者结点)构成的。这些个节点一般是动态内存申请得来的,所以每个节点的地址没有关联,是随机的,可能动态申请的时候申请到了连续的空间,更多可能是申请到不连续的空间,也就是说链表的物理结构不一定连续,。既然每个节点的地址是随机的,那我们如何管理链表呢? 

其实也很简单,拿不带头非循环单向链表来说,如上逻辑结构可知,只要节点有俩个数据域即可,一个数据域存放所需存入的值(即有效数据),另一个数据域存放下一个节点的地址(最后一个节点保存空指针)。这样我们就可以通过第一个节点找到第二个节点、第二个节点找到第三个节点……这样就可以管理链表了。

了解了链表的特点,那我们对于数据的增删改等操作,更改节点内存储的地址即可,不必挪动数据。而且节点是一个个动态申请得到的,想要多少就申请多少,自然就避免了扩容有浪费的情况。这样子就很好避免的顺序表的缺陷!

画图方便理解:

2.链表的分类

实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

1.单向或者双向

2.带头(哨兵位)或者不带头

3.循环或者非循环

 虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:

1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。

2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了。

咱们这篇博客实现的是无头单向非循环链表。 

3.无头单向非循环链表的实现

具体我们实现这些无头单向非循环链表(以下简称单链表)的增删查改等等功能:

  1. typedef int SLTDateType; //有效数据类型,方便后续维护代码
  2. //定义单链表节点
  3. typedef struct SListNode
  4. {
  5. SLTDateType data; //有效数据
  6. struct SListNode* next; //下一个节点的地址
  7. }SListNode;
  8. // 单链表打印
  9. void SListPrint (SListNode * plist);
  10. // 单链表尾插
  11. void SListPushBack(SListNode** pplist, SLTDateType x);
  12. // 单链表的头插
  13. void SListPushFront(SListNode** pplist, SLTDateType x);
  14. // 单链表的尾删
  15. void SListPopBack(SListNode** pplist);
  16. // 单链表头删
  17. void SListPopFront(SListNode** pplist);
  18. // 单链表查找
  19. SListNode* SListFind(SListNode* plist, SLTDateType x);
  20. // 单链表在pos位置之后插入值
  21. void SListInsertAfter(SListNode* pos, SLTDateType x);
  22. // 单链表删除pos位置之后的值
  23. void SListEraseAfter(SListNode* pos);
  24. // 在pos的前面插入值
  25. void SLTInsert(SListNode** pphead, SListNode* pos, SLTDateType x);
  26. // 删除pos位置的值
  27. void SLTErase(SListNode** pphead, SListNode* pos);
  28. //销毁单链表
  29. void SLTDestroy(SListNode** pphead);

好了好了,一个个来实现吧!

3.1.单链表打印 

  1. //单链表打印
  2. void SListPrint(SListNode* plist)
  3. {
  4. SListNode* cur = plist;
  5. while (cur != NULL)
  6. {
  7. printf("%d->", cur->data);
  8. cur = cur->next;
  9. }
  10. printf("NULL\n");
  11. }

这个打印的实现还是很简单的,我们只要遍历单链表在将每个节点的数据打印出来即可。

3.2.单链表尾插

  1. //动态申请一个节点
  2. SListNode* BuySListNode(SLTDateType x)
  3. {
  4. SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
  5. if (newnode == NULL)
  6. {
  7. perror("malloc fail");
  8. exit(-1);
  9. }
  10. newnode->data = x;
  11. newnode->next = NULL;
  12. return newnode;
  13. }
  14. //单链表尾插
  15. void SListPushBack(SListNode** pplist, SLTDateType x)
  16. {
  17. assert(pplist);
  18. if (*pplist == NULL)//单链表为空
  19. {
  20. *pplist = BuySListNode(x);
  21. }
  22. else//单链表不为空
  23. {
  24. SListNode* tail = *pplist;
  25. while (tail->next != NULL)//找尾
  26. {
  27. tail = tail->next;
  28. }
  29. SListNode* newnode = BuySListNode(x);
  30. tail->next = newnode;
  31. }
  32. }

这个尾插的实现来说,正常情况下先找到单链表的最后一个节点(找尾),在让最后一个节点存储新申请节点的地址即可,所以要调用动态申请一个节点的函数(BuySListNode),这个函数已经让新申请的节点存储空指针和需要保存的数据了。 但是要区别单链表是否为空(如果不加以区分单链表是否为空的话就会访问空指针),如果为空的话直接让*pplist保存新申请的节点地址即可。

3.3.单链表头插

  1. //动态申请一个节点
  2. SListNode* BuySListNode(SLTDateType x)
  3. {
  4. SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
  5. if (newnode == NULL)
  6. {
  7. perror("malloc fail");
  8. exit(-1);
  9. }
  10. newnode->data = x;
  11. newnode->next = NULL;
  12. return newnode;
  13. }
  14. //单链表头插
  15. void SListPushFront(SListNode** pplist, SLTDateType x)
  16. {
  17. assert(pplist);
  18. SListNode* newnode = BuySListNode(x);
  19. newnode->next = *pplist;
  20. *pplist = newnode;
  21. }

对于头插的实现,只要让新申请的节点 存储原来*pplist的地址,让*pplist保存新申请的节点的地址即可。

3.4.单链表尾删

  1. //单链表尾删
  2. void SListPopBack(SListNode** pplist)
  3. {
  4. assert(pplist);
  5. assert(*pplist);
  6. SListNode* tail = *pplist;
  7. SListNode* fronttail = *pplist;
  8. while (tail->next != NULL)//找尾节点和尾节点前一个节点
  9. {
  10. fronttail = tail;
  11. tail = tail->next;
  12. }
  13. if (fronttail->next == NULL)//一个节点
  14. {
  15. *pplist = NULL;
  16. free(tail);
  17. tail = NULL;
  18. fronttail = NULL;
  19. }
  20. else//多个节点
  21. {
  22. free(tail);
  23. tail = NULL;
  24. fronttail->next = NULL;
  25. }
  26. }

对于尾删,我们要区分单链表为空、单链表有一个节点和单链表有多个节点的情况。如果单链表为空就不能删除,断言即可。单链表一个节点的话,让*pplist保存空指针,free掉尾节点(也是头节点)。 单链表有多个节点的话,free掉尾节点,让尾节点前一个节点保存空指针即可。(如果不区分一个节点和多个节点的情况,一律按多个节点情况来处理的话,当只有一个节点时,fronttail会成为野指针。)。

3.5.单链表头删

  1. //单链表头删
  2. void SListPopFront(SListNode** pplist)
  3. {
  4. assert(pplist);
  5. assert(*pplist);
  6. SListNode* next = (*pplist)->next;
  7. free(*pplist);
  8. *pplist = next;
  9. }

这个简单,只要free掉头节点(free掉之前需要保存头节点下一个节点地址,不然的话就找不到头节点下一个节点了),*pplist保存头节点下一个节点地址即可。 

3.6.单链表查找

  1. //单链表查找
  2. SListNode* SListFind(SListNode* plist, SLTDateType x)
  3. {
  4. SListNode* cur = plist;
  5. while (cur != NULL)
  6. {
  7. if (cur->data == x)
  8. {
  9. return cur;
  10. }
  11. cur = cur->next;
  12. }
  13. return NULL;
  14. }

这个实现的话,只要遍历单链表找到单链表节点中第一个出现的与x相等的val ,再返回该节点的地址即可,找不到就返回空指针。

3.7.单链表在pos位置之和插入值

  1. //动态申请一个节点
  2. SListNode* BuySListNode(SLTDateType x)
  3. {
  4. SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
  5. if (newnode == NULL)
  6. {
  7. perror("malloc fail");
  8. exit(-1);
  9. }
  10. newnode->data = x;
  11. newnode->next = NULL;
  12. return newnode;
  13. }
  14. // 单链表在pos位置之后插入值
  15. void SListInsertAfter(SListNode* pos, SLTDateType x)
  16. {
  17. assert(pos);
  18. SListNode* newnode = BuySListNode(x);
  19. SListNode* next = pos->next;
  20. pos->next = newnode;
  21. newnode->next = next;
  22. }

实现这个功能的话,我们需要知道pos的值(这个值是某个节点的地址,可以通过单链表查找获得),然后的话让pos指向的节点存储新申请节点的地址,新申请的节点存储pos指向的节点的下一个节点的地址即可(这个地址记得提前用变量存储下来,如果在改变pos指向的节点存储的地址之前没有存储下来的话,就找不到pos指向节点的下一个节点了)。

3.8.单链表删除pos位置之后的值 

  1. // 单链表删除pos位置之后的值
  2. void SListEraseAfter(SListNode* pos)
  3. {
  4. assert(pos);
  5. assert(pos->next);//防止删pos指向尾节点
  6. SListNode* next = pos->next->next;
  7. free(pos->next);
  8. pos->next = next;
  9. }

这里需要注意防止单链表为空和防止pos指向尾节点(尾节点后面为空,不可删),断言即可。这个实现大致就是让pos指向的节点存储pos指向节点的后两个节点的地址,free掉pos指向节点后一个节点即可。

3.9.在pos的前面插入值

  1. //动态申请一个节点
  2. SListNode* BuySListNode(SLTDateType x)
  3. {
  4. SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
  5. if (newnode == NULL)
  6. {
  7. perror("malloc fail");
  8. exit(-1);
  9. }
  10. newnode->data = x;
  11. newnode->next = NULL;
  12. return newnode;
  13. }
  14. // 在pos的前面插入值
  15. void SLTInsert(SListNode** pphead, SListNode* pos, SLTDateType x)
  16. {
  17. assert(pphead);
  18. assert((!*pphead && !pos) || (*pphead && pos));
  19. if (*pphead == pos)
  20. {
  21. SListPushBack(pphead, x);
  22. }
  23. else
  24. {
  25. SListNode* frontpos = *pphead;
  26. while (frontpos->next != pos)//找pos前一个节点
  27. {
  28. frontpos = frontpos->next;
  29. }
  30. SListNode* newnode = BuySListNode(x);
  31. SListNode* next = frontpos->next;
  32. frontpos->next = newnode;
  33. newnode->next = next;
  34. }
  35. }

如果单链表为空,直接调用单链表尾插(单链表头插也行)即可。不为空就找到pos指向节点的前一个节点,让pos指向节点的前一个节点存储新申请节点地址,让新申请节点存储pos指向节点的地址即可。 

3.10.删除pos位置的值

  1. // 删除pos位置的值
  2. void SLTErase(SListNode** pphead, SListNode* pos)
  3. {
  4. assert(pphead);
  5. assert(*pphead);//没有节点
  6. assert(pos);
  7. if ((*pphead)->next == NULL)//一个节点
  8. {
  9. SListPopFront(pphead);
  10. }
  11. else
  12. {
  13. SListNode* frontpos = *pphead;
  14. while (frontpos->next != pos)//找pos前一个节点
  15. {
  16. frontpos = frontpos->next;
  17. }
  18. SListNode* next = pos->next;
  19. free(pos);
  20. frontpos->next = next;
  21. }
  22. }

注意断言,防止单链表为空,为空不能删除。如果单链表有一个节点,直接调用单链表头删(单链表尾删也行)即可。如果有单链表有多个节点,大致的话让pos指向的节点前一个节点存储pos指向节点后一个节点地址,free掉pos指向节点即可。

3.11.销毁单链表

  1. //销毁单链表
  2. void SLTDestroy(SListNode** pphead)
  3. {
  4. assert(pphead);
  5. SListNode* cur = *pphead;
  6. while (cur)
  7. {
  8. SListNode* next = cur->next;
  9. free(cur);
  10. cur = next;
  11. }
  12. *pphead = NULL;
  13. }

如果不再使用单链表的话,可以销毁单链表。虽然单链表是动态申请的,不手动销毁的话结束程序也会自动销毁 ,但手动销毁是一个好习惯。这个实现也简单,遍历单链表一一销毁节点即可。

4.单链表的小应用

对于上面的单链表增删查改等等实现来说,鼠鼠我讲解的只是大概思想,我们只要懂得这些思想再注意一些细节就可完成上面代码的实现。单链表的实现不是唯一的,上面代码只是一种参考,最重要要懂得单链表的含义和增删查改等等思想。

鼠鼠我还是一样,写了一个工程来验证单链表增删查改等等功能的实现,有兴趣的读者老爷可以将以下三个文件(上面的实现代码都在slist.c里面了)放到一个工程玩玩!

4.1.slist.h

  1. #pragma once
  2. #include<stdio.h>
  3. #include<assert.h>
  4. #include<stdlib.h>
  5. typedef int SLTDateType;
  6. typedef struct SListNode
  7. {
  8. SLTDateType data;
  9. struct SListNode* next;
  10. }SListNode;
  11. // 单链表打印
  12. void SListPrint (SListNode * plist);
  13. // 单链表尾插
  14. void SListPushBack(SListNode** pplist, SLTDateType x);
  15. // 单链表的头插
  16. void SListPushFront(SListNode** pplist, SLTDateType x);
  17. // 单链表的尾删
  18. void SListPopBack(SListNode** pplist);
  19. // 单链表头删
  20. void SListPopFront(SListNode** pplist);
  21. // 单链表查找
  22. SListNode* SListFind(SListNode* plist, SLTDateType x);
  23. // 单链表在pos位置之后插入值
  24. void SListInsertAfter(SListNode* pos, SLTDateType x);
  25. // 单链表删除pos位置之后的值
  26. void SListEraseAfter(SListNode* pos);
  27. // 在pos的前面插入值
  28. void SLTInsert(SListNode** pphead, SListNode* pos, SLTDateType x);
  29. // 删除pos位置的值
  30. void SLTErase(SListNode** pphead, SListNode* pos);
  31. //销毁单链表
  32. void SLTDestroy(SListNode** pphead);

4.2.slist.c

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include"slist.h"
  3. //动态申请一个节点
  4. SListNode* BuySListNode(SLTDateType x)
  5. {
  6. SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
  7. if (newnode == NULL)
  8. {
  9. perror("malloc fail");
  10. exit(-1);
  11. }
  12. newnode->data = x;
  13. newnode->next = NULL;
  14. return newnode;
  15. }
  16. //单链表尾插
  17. void SListPushBack(SListNode** pplist, SLTDateType x)
  18. {
  19. assert(pplist);
  20. if (*pplist == NULL)//单链表为空
  21. {
  22. *pplist = BuySListNode(x);
  23. }
  24. else//单链表不为空
  25. {
  26. SListNode* tail = *pplist;
  27. while (tail->next != NULL)//找尾
  28. {
  29. tail = tail->next;
  30. }
  31. SListNode* newnode = BuySListNode(x);
  32. tail->next = newnode;
  33. }
  34. }
  35. //单链表打印
  36. void SListPrint(SListNode* plist)
  37. {
  38. SListNode* cur = plist;
  39. while (cur != NULL)
  40. {
  41. printf("%d->", cur->data);
  42. cur = cur->next;
  43. }
  44. printf("NULL\n");
  45. }
  46. //单链表头插
  47. void SListPushFront(SListNode** pplist, SLTDateType x)
  48. {
  49. assert(pplist);
  50. SListNode* newnode = BuySListNode(x);
  51. newnode->next = *pplist;
  52. *pplist = newnode;
  53. }
  54. //单链表尾删
  55. void SListPopBack(SListNode** pplist)
  56. {
  57. assert(pplist);
  58. assert(*pplist);
  59. SListNode* tail = *pplist;
  60. SListNode* fronttail = *pplist;
  61. while (tail->next != NULL)//找尾节点和尾节点前一个节点
  62. {
  63. fronttail = tail;
  64. tail = tail->next;
  65. }
  66. if (fronttail->next == NULL)//一个节点
  67. {
  68. *pplist = NULL;
  69. free(tail);
  70. tail = NULL;
  71. fronttail = NULL;
  72. }
  73. else//多个节点
  74. {
  75. free(tail);
  76. tail = NULL;
  77. fronttail->next = NULL;
  78. }
  79. }
  80. //单链表头删
  81. void SListPopFront(SListNode** pplist)
  82. {
  83. assert(pplist);
  84. assert(*pplist);
  85. SListNode* next = (*pplist)->next;
  86. free(*pplist);
  87. *pplist = next;
  88. }
  89. //单链表查找
  90. SListNode* SListFind(SListNode* plist, SLTDateType x)
  91. {
  92. SListNode* cur = plist;
  93. while (cur != NULL)
  94. {
  95. if (cur->data == x)
  96. {
  97. return cur;
  98. }
  99. cur = cur->next;
  100. }
  101. return NULL;
  102. }
  103. // 单链表在pos位置之后插入值
  104. void SListInsertAfter(SListNode* pos, SLTDateType x)
  105. {
  106. assert(pos);
  107. SListNode* newnode = BuySListNode(x);
  108. SListNode* next = pos->next;
  109. pos->next = newnode;
  110. newnode->next = next;
  111. }
  112. // 单链表删除pos位置之后的值
  113. void SListEraseAfter(SListNode* pos)
  114. {
  115. assert(pos);
  116. assert(pos->next);//防止删pos指向尾节点
  117. SListNode* next = pos->next->next;
  118. free(pos->next);
  119. pos->next = next;
  120. }
  121. // 在pos的前面插入值
  122. void SLTInsert(SListNode** pphead, SListNode* pos, SLTDateType x)
  123. {
  124. assert(pphead);
  125. assert((!*pphead && !pos) || (*pphead && pos));
  126. if (*pphead == pos)
  127. {
  128. SListPushBack(pphead, x);
  129. }
  130. else
  131. {
  132. SListNode* frontpos = *pphead;
  133. while (frontpos->next != pos)//找pos前一个节点
  134. {
  135. frontpos = frontpos->next;
  136. }
  137. SListNode* newnode = BuySListNode(x);
  138. SListNode* next = frontpos->next;
  139. frontpos->next = newnode;
  140. newnode->next = next;
  141. }
  142. }
  143. // 删除pos位置的值
  144. void SLTErase(SListNode** pphead, SListNode* pos)
  145. {
  146. assert(pphead);
  147. assert(*pphead);//没有节点
  148. assert(pos);
  149. if ((*pphead)->next == NULL)//一个节点
  150. {
  151. SListPopFront(pphead);
  152. }
  153. else
  154. {
  155. SListNode* frontpos = *pphead;
  156. while (frontpos->next != pos)//找pos前一个节点
  157. {
  158. frontpos = frontpos->next;
  159. }
  160. SListNode* next = pos->next;
  161. free(pos);
  162. frontpos->next = next;
  163. }
  164. }
  165. //销毁单链表
  166. void SLTDestroy(SListNode** pphead)
  167. {
  168. assert(pphead);
  169. SListNode* cur = *pphead;
  170. while (cur)
  171. {
  172. SListNode* next = cur->next;
  173. free(cur);
  174. cur = next;
  175. }
  176. *pphead = NULL;
  177. }

4.3.test.c

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include"slist.h"
  3. void menu()
  4. {
  5. printf("**********************\n");
  6. printf("********0.退出********\n");
  7. printf("****1.头插 2.头删****\n");
  8. printf("****3.尾插 4.尾删****\n");
  9. printf("****5.查找 6.打印****\n");
  10. printf("*7.在pos位置之后插入值\n");
  11. printf("*8.删除pos位置之后的值\n");
  12. printf("*9.在pos的前面插入值**\n");
  13. printf("*10.删除pos位置的值***\n");
  14. printf("**********************\n");
  15. }
  16. int main()
  17. {
  18. SListNode* pplist = NULL;
  19. int input;
  20. do
  21. {
  22. menu();
  23. printf("请输入你想操作的数字:->");
  24. scanf("%d", &input);
  25. if (input == 0)
  26. {
  27. SLTDestroy(&pplist);
  28. printf("\n");
  29. break;
  30. }
  31. else if (input == 1)
  32. {
  33. int number = 0;
  34. printf("请输入你要头插数据的个数:->");
  35. scanf("%d", &number);
  36. printf("请输入你要头插的数据:->");
  37. while (number--)
  38. {
  39. SLTDateType x = 0;
  40. scanf("%d", &x);
  41. SListPushFront(&pplist, x);
  42. }
  43. printf("\n");
  44. }
  45. else if (input == 2)
  46. {
  47. SListPopFront(&pplist);
  48. printf("\n");
  49. }
  50. else if (input == 3)
  51. {
  52. int number = 0;
  53. printf("请输入你要尾插数据的个数:->");
  54. scanf("%d", &number);
  55. printf("请输入你要尾插的数据:->");
  56. int i = 0;
  57. for (i = 0; i < number; i++)
  58. {
  59. SLTDateType x = 0;
  60. scanf("%d", &x);
  61. SListPushBack(&pplist, x);
  62. }
  63. printf("\n");
  64. }
  65. else if (input == 4)
  66. {
  67. SListPopBack(&pplist);
  68. printf("\n");
  69. }
  70. else if (input == 5)
  71. {
  72. SLTDateType x = 0;
  73. printf("请输入你要查找的值:->");
  74. scanf("%d", &x);
  75. SListNode* p = SListFind(pplist, x);
  76. if (p != NULL)
  77. {
  78. printf("你要查找的值地址是%p\n", p);
  79. }
  80. else
  81. {
  82. printf("找不到!\n");
  83. }
  84. printf("\n");
  85. }
  86. else if (input == 6)
  87. {
  88. SListPrint(pplist);
  89. printf("\n");
  90. }
  91. else if (input == 7)
  92. {
  93. SLTDateType x = 0,pos = 0;
  94. printf("请分别输入你要插入的值及pos指向的值:->");
  95. scanf("%d %d", &x, &pos);
  96. SListInsertAfter( SListFind(pplist,pos), x);
  97. printf("\n");
  98. }
  99. else if (input == 8)
  100. {
  101. SLTDateType pos = 0;
  102. printf("请输入pos指向的值:->");
  103. scanf("%d", &pos);
  104. SListEraseAfter(SListFind(pplist, pos));
  105. printf("\n");
  106. }
  107. else if (input == 9)
  108. {
  109. SLTDateType x = 0, pos = 0;
  110. printf("请分别输入你要插入的值及pos指向的值:->");
  111. scanf("%d %d", &x, &pos);
  112. SLTInsert(&pplist, SListFind(pplist, pos), x);
  113. printf("\n");
  114. }
  115. else if (input == 10)
  116. {
  117. SLTDateType pos = 0;
  118. printf("请输入pos指向的值:->");
  119. scanf("%d", &pos);
  120. SLTErase(&pplist, SListFind(pplist, pos));
  121. printf("\n");
  122. }
  123. else
  124. {
  125. printf("输入错误,请重新输入:->");
  126. }
  127. } while (input);
  128. return 0;
  129. }

5.ending 

鼠鼠我呀不怎么会写博客,读者老爷看到这里如果觉得不好就多多包涵,看看图一乐也不是不行。当然如有不足,恳请斧正哈!

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

闽ICP备14008679号