六.查找 插入 释放 打印
1.查找 SListfind
在插入和释放前,都需要调用 find 函数,来找到希望插入或是释放的位置。
1. SLNode* SListfind(SLNode* phead, SLdatatype x) 2. { 3. SLNode* pos = phead; 4. while (pos) 5. { 6. if (pos->data == x) 7. { 8. return pos; 9. } 10. pos = pos->next; 11. } 12. }
2.插入 SListinsert
如果是链表中只有一个节点,就变成了头插,只需要调用头插函数就行了,如果是空表也不用担心,可以设置成不调用函数;
在插入前,需要找到指定位置 pos 的前驱 pre,
使pre->next=newnode , newnode->next=pos
如图所示,假设在3的前一个位置插入数据:
1. void SListinsert(SLNode** pphead, SLNode* pos,SLdatatype x) 2. { 3. SLNode* newnode = BuySListNode(x); 4. if (pos->next == NULL) 5. { 6. SListpushfront(pphead, x); 7. } 8. else 9. { 10. SLNode* pre = *pphead; 11. while (pre->next != pos) 12. { 13. pre = pre->next; 14. } 15. pre->next = newnode; 16. newnode->next = pos; 17. } 18. }
3.释放 SListerase
释放前:
1.如果只有一个节点,则直接释放头节点,再置为空即可;
2.如果不止一个节点,还需找到要释放的位置的前一个节点 pre ,将 pre 的 next 指向 pos 的next,然后再释放;
如图所示,假设要释放掉3这个节点:
1. void SListerase(SLNode** pphead, SLNode* pos, SLdatatype x) 2. { 3. if (pos->next == NULL) 4. { 5. free(*pphead); 6. *pphead = NULL; 7. } 8. else 9. { 10. SLNode* pre = *pphead; 11. while (pre->next !=pos) 12. { 13. pre = pre->next; 14. } 15. pre->next = pos->next; 16. free(pos); 17. } 18. }
4.打印 SListprint
虽然可以直接用头节点 phead 遍历,但博主还是推荐定义一个新的结构体指针 cur ,把phead 的值赋给 cur ,会显得更优雅;
注意这里的 while 里的式子要写成 cur ,如果 写成 cur->next ,那么最终打印出来的结果会少一个节点的数据。
1. void SListprint(SLNode* phead) 2. { 3. SLNode* cur = phead; 4. while (cur != NULL) 5. { 6. printf("%d->", cur->data); 7. cur = cur->next; 8. } 9. printf("NULL\n"); 10. }
七.源码
1.SList.h
1. #define _CRT_SECURE_NO_WARNINGS 2. 3. 4. #include <stdio.h> 5. #include <stdlib.h> 6. #include <assert.h> 7. 8. typedef int SLdatatype; 9. 10. typedef struct SListNode 11. { 12. SLdatatype data; 13. struct SListNode* next; 14. }SLNode; 15. 16. 17. void SListprint(SLNode* phead); //打印 18. 19. void SListpushback(SLNode** pphead,SLdatatype x); //尾插 20. 21. void SListpushfront(SLNode** pphead, SLdatatype x); //头插 22. 23. void SListpopfront(SLNode** pphead); //头删 24. 25. void SListpopback(SLNode** pphead); //尾删 26. 27. SLNode* SListfind(SLNode* phead,SLdatatype x); //查找 28. 29. void SListinsert(SLNode** pphead, SLNode* pos,SLdatatype x); //插入 30. 31. void SListerase(SLNode** pphead, SLNode* pos, SLdatatype x); //释放
2.SList.c
1. #define _CRT_SECURE_NO_WARNINGS 2. 3. #include "SList.h" 4. 5. 6. void SListprint(SLNode* phead) 7. { 8. SLNode* cur = phead; 9. while (cur != NULL) 10. { 11. printf("%d->", cur->data); 12. cur = cur->next; 13. } 14. printf("NULL\n"); 15. } 16. 17. 18. SLNode* BuySListNode(SLdatatype x) 19. { 20. SLNode* newnode = (SLNode*)malloc(sizeof(SLNode)); 21. assert(newnode); 22. newnode->data = x; 23. newnode->next = NULL; 24. return newnode; 25. } 26. 27. void SListpushback(SLNode** pphead,SLdatatype x) 28. { 29. SLNode* newnode = BuySListNode(x); 30. if (*pphead == NULL) 31. { 32. *pphead = newnode; 33. } 34. else 35. { 36. SLNode* tail = *pphead; //寻找尾节点 37. while (tail->next != NULL) 38. { 39. tail = tail->next; 40. } 41. tail->next = newnode; 42. } 43. } 44. 45. 46. void SListpushfront(SLNode** pphead, SLdatatype x) 47. { 48. SLNode* newnode = BuySListNode(x); 49. newnode->next = *pphead; 50. *pphead = newnode; 51. } 52. 53. 54. void SListpopfront(SLNode** pphead) 55. { 56. if (*pphead == NULL) 57. { 58. return; 59. } 60. else 61. { 62. SLNode* next = (*pphead)->next; 63. free(*pphead); 64. *pphead = next; 65. } 66. } 67. 68. 69. void SListpopback(SLNode** pphead) 70. { 71. if (*pphead == NULL) 72. { 73. return; 74. } 75. else if ((*pphead)->next == NULL) 76. { 77. free(*pphead); 78. *pphead = NULL; 79. } 80. else 81. { 82. SLNode* pre = NULL; 83. SLNode* tail = *pphead; 84. while (tail->next != NULL) 85. { 86. pre = tail; 87. tail = tail->next; 88. } 89. pre->next = NULL; 90. } 91. } 92. 93. 94. SLNode* SListfind(SLNode* phead, SLdatatype x) 95. { 96. SLNode* pos = phead; 97. while (pos) 98. { 99. if (pos->data == x) 100. { 101. return pos; 102. } 103. pos = pos->next; 104. } 105. } 106. 107. 108. void SListinsert(SLNode** pphead, SLNode* pos,SLdatatype x) 109. { 110. SLNode* newnode = BuySListNode(x); 111. if (pos->next == NULL) 112. { 113. SListpushfront(pphead, x); 114. } 115. else 116. { 117. SLNode* pre = *pphead; 118. while (pre->next != pos) 119. { 120. pre = pre->next; 121. } 122. pre->next = newnode; 123. newnode->next = pos; 124. } 125. } 126. 127. 128. 129. void SListerase(SLNode** pphead, SLNode* pos, SLdatatype x) 130. { 131. if (pos->next == NULL) 132. { 133. free(*pphead); 134. *pphead = NULL; 135. } 136. else 137. { 138. SLNode* pre = *pphead; 139. while (pre->next !=pos) 140. { 141. pre = pre->next; 142. } 143. pre->next = pos->next; 144. free(pos); 145. } 146. }
3.test.c
博主写的主函数只是用来测试单链表的,写起主函数来也不难,大家可以自行编写。
1. #include "SList.h" 2. 3. 4. void testSList1() 5. { 6. SLNode* plist = NULL; 7. 8. SListpushback(&plist,1); 9. SListpushback(&plist,2); 10. SListpushback(&plist,3); 11. SListpushback(&plist,4); 12. SListprint(plist); 13. SListpushfront(&plist, 0); 14. SListprint(plist); 15. SListpopfront(&plist); 16. SListpopfront(&plist); 17. SListpopfront(&plist); 18. SListprint(plist); 19. SListpopback(&plist); 20. SListpopback(&plist); 21. SListpopback(&plist); 22. SListprint(plist); 23. } 24. 25. void testSList2() 26. { 27. SLNode* plist = NULL; 28. SListpushback(&plist, 1); 29. SListpushback(&plist, 2); 30. SListpushback(&plist, 3); 31. SListpushback(&plist, 4); 32. SLNode* pos = SListfind(plist, 3); 33. if (pos) 34. { 35. SListinsert(&plist,pos, 20); 36. SListprint(plist); 37. } 38. pos = SListfind(plist, 2); 39. if (pos) 40. { 41. SListerase(&plist,pos,2); 42. SListprint(plist); 43. } 44. 45. } 46. 47. int main() 48. { 49. //testSList1(); 50. testSList2(); 51. return 0; 52. }
八.单链表的一些问题
在单链表中,要想找到某一个数据,就需要从头节点开始,所以单链表是非随机存取的存储结构,且要想对单链表进行一些操作,总是要找到前驱节点,有时还需判断一些特殊情况,有什么办法能解决这些问题呢?
博主将在下篇双向带头循环链表中讲解,敬情期待~
🤩🥰本篇文章到此就结束了,如有错误或是建议,欢迎小伙伴们提出~😍😃
🐲👻希望可以多多支持博主哦~🥰😍
🤖🐯谢谢你的阅读~👻🦁