当前位置:   article > 正文

单向链表的基本操作(常见面试题详解)_单项列表克服了数组的什么缺陷

单项列表克服了数组的什么缺陷
一、什么是链表
     链表是一种常见的非常重要的数据结构,是动态进行存储分配的一种结构。其中数据元素的逻辑顺序是通过链表中的指针链接次序实现的,链表中的每一个元素都称为结点,链表就是由这一系列结点组成的,其结点可在运行时动态生成。每一个结点都是由两部分组成,一部分是存储数据元素的数据域,另一部分是存储下一结点地址的指针域。
    链表的类型有:单向链表、双向链表、循环链表。
    链表的优点:1、克服了数组预先知道数据大小的缺点;
                          2、动态管理内存空间,可充分利用内存空间;
                          3、可插入和移除表上任意位置的结点。
    链表的缺点:1、增加了指针域,空间开销大;
                          2、不能随机读取数据。
二、单向链表的基本操作
1、头插:从链表首部插入结点,只需要创建一块内存空间,将数据放进数据域,将原链表的首元素地址放进新创建的指针域当中。
  1. void Pushfront(pList* plist, Datatype data)
  2. {
  3. assert(plist != NULL);
  4. pNode p = NULL;
  5. p =(pNode) malloc(sizeof(node_t));
  6. if (p == NULL)
  7. {
  8. perror("malloc()");
  9. exit(EXIT_FAILURE);
  10. }
  11. p->data = data;
  12. p->next = NULL;
  13. p->next = *plist;
  14. *plist = p;
  15. }
2、尾插:从链表尾部插入结点,需要创建一块内存空间,将地址放进原链表尾部的结点的指针域当中,然后将指针域制空即可。
  1. void Pushback(pList* plist,Datatype data)
  2. {
  3. assert(plist != NULL);
  4. pNode cur = *plist;
  5. pNode p = NULL;
  6. p =(pNode) malloc(sizeof(node_t));
  7. if (p == NULL)
  8. {
  9. perror("malloc()");
  10. exit(EXIT_FAILURE);
  11. }
  12. memset(p, 0, sizeof(node_t));
  13. p->data = data;
  14. if (cur == NULL)
  15. {
  16. *plist = p;
  17. }
  18. else
  19. {
  20. while (cur->next)
  21. {
  22. cur = cur->next;
  23. }
  24. cur->next = p;
  25. }
  26. }
3、头删:释放掉第一个结点,头指针指向下一个结点,即可。
  1. void Popfront(pList* plist)
  2. {
  3. assert(plist != NULL);
  4. pList cur = *plist;
  5. if (cur == NULL)
  6. {
  7. return;
  8. }
  9. else
  10. {
  11. *plist = cur->next;
  12. free(cur);
  13. cur->next = NULL;
  14. }
  15. }
4、尾删:释放掉最后一个结点,将倒数第二个结点的指针置为空指针。
  1. void Popback(pList* plist)
  2. {
  3. assert(plist != NULL);
  4. pList fast = *plist;
  5. pList slow = NULL;
  6. if (*plist == NULL)
  7. {
  8. return;
  9. }
  10. while (fast!=NULL)
  11. {
  12. slow = fast;
  13. fast = fast->next;
  14. }
  15. if (slow != NULL)
  16. {
  17. slow->next = NULL;
  18. free(fast);
  19. }
  20. else
  21. {
  22. free(fast);
  23. *plist = NULL;
  24. }
  25. }
5、销毁链表:逐个释放结点所占的内存空间。
  1. void Destroy(pList* plist)
  2. {
  3. assert(plist != NULL);
  4. pList cur = NULL;
  5. while (*plist)
  6. {
  7. cur = (*plist)->next;
  8. free(*plist);
  9. *plist = NULL;
  10. *plist = cur;
  11. }
  12. }
6、查找某一个结点。
  1. pNode Find(pList plist, Datatype data)
  2. {
  3. pNode cur =plist;
  4. while (cur)
  5. {
  6. if (cur->data == data)
  7. {
  8. return cur;
  9. }
  10. cur = cur->next;
  11. }
  12. return NULL;
  13. }
7、链表的逆序:遍历一遍链表,将链表里每个结点的指针域里存放的地址更改为其上一个结点的地址,并将原链表的第一个结点的指针域存放空指针。
  1. void Invert_list(pList *plist)
  2. {
  3. if (((*plist) == NULL) || ((*plist)->next == NULL))
  4. {
  5. return;
  6. }
  7. else
  8. {
  9. pList cur1 = *plist;
  10. pList cur2 = (*plist)->next;
  11. pList cur3 = (*plist)->next->next;
  12. pList tmp = NULL;
  13. while (1)
  14. {
  15. cur2->next = cur1;
  16. cur1->next = tmp;
  17. tmp = cur1;
  18. if (cur3 == NULL)
  19. {
  20. break;
  21. }
  22. else
  23. {
  24. cur1 = cur2;
  25. cur2 = cur3;
  26. cur3 = cur3->next;
  27. }
  28. }
  29. *plist = cur2;
  30. }
  31. }
8、顺序打印链表
  1. void Display(pList plist)
  2. {
  3. pList cur = plist;
  4. for (; cur != NULL; cur = cur->next)
  5. {
  6. printf("%d--->", cur->data);
  7. }
  8. printf("over\n");
  9. }
9、逆序打印链表:最简便的方法莫过于递归实现。
  1. void Invert_display(pList plist)
  2. {
  3. if(plist!=NULL)
  4. {
  5. Invert_display(plist->next);
  6. printf("%d--->", plist->data);
  7. }
  8. else
  9. {
  10. return;
  11. }
  12. }
10、删除一个非尾结点:找到要删除的结点的下一个结点,将该节点的内容放进要删除的结点中,释放该结点。


  1. void Del_Not_Tail(pNode pos)
  2. {
  3. assert(pos != NULL);
  4. pNode cur = pos->next;
  5. if (cur != NULL)
  6. {
  7. pos->next = cur->next;
  8. pos->data = cur->data;
  9. }
  10. else
  11. {
  12. return;
  13. }
  14. free(cur);
  15. cur = NULL;
  16. }
11、在指定位置前插入一个结点:创建一个结点,将该结点插入到指定位置后,然后将指定位置的数据放入创建的结点中,指定位置的数据域存放需要新加入的数据。



  1. void Insert_Front_Node(pNode pos, Datatype data)
  2. {
  3. assert(pos != NULL);
  4. pNode p = NULL;
  5. p = (pNode)malloc(sizeof(node_t));
  6. if (p == NULL)
  7. {
  8. perror("malloc()");
  9. exit(EXIT_FAILURE);
  10. }
  11. p->next = pos->next;
  12. p->data = pos->data;
  13. pos->data = data;
  14. pos->next = p;
  15. }
12、合并有序链表
  1. pList Merge(pList* plist1, pList* plist2)
  2. {
  3. assert(plist1 != NULL);
  4. assert(plist2 != NULL);
  5. pList head = NULL;
  6. pList p = NULL;
  7. pList cur1 = *plist1;
  8. pList cur2 = *plist2;
  9. if (cur1->data < cur2->data)
  10. {
  11. head = cur1;
  12. cur1 = cur1->next;
  13. }
  14. else
  15. {
  16. head = cur2;
  17. cur2 = cur2->next;
  18. }
  19. p = head;
  20. while ((cur1 != NULL) && (cur2 != NULL))
  21. {
  22. if (cur1->data < cur2->data)
  23. {
  24. p->next = cur1;
  25. cur1 = cur1->next;
  26. }
  27. else
  28. {
  29. p->next = cur2;
  30. cur2 = cur2->next;
  31. }
  32. p = p->next;
  33. }
  34. if (cur1 == NULL)
  35. {
  36. p->next = cur2;
  37. }
  38. else if (cur2 == NULL)
  39. {
  40. p->next = cur1;
  41. }
  42. return head;
  43. }
13、约瑟夫环问题:一共有n个人,开始报数,报到第k个的人自杀,然后从下一个继续报数,问最后自杀的人是谁?
        通过链表,我们不仅可以找出最后自杀的人,还可以将n个人自杀的顺序找出来。遍历链表,利用计数器,每数到k,就将此时指针所指向的结点释放,将下一个结点挂到上一个节点上。
  1. void JosephCycle(pList plist, int k)
  2. {
  3. pList cur1 = plist;
  4. pList cur2 = plist;
  5. if (k >= 2)
  6. {
  7. while (1)
  8. {
  9. int count = k;
  10. pNode tmp = NULL;
  11. if (cur1 == cur1->next)
  12. {
  13. printf("%d\n", cur1->data);
  14. break;
  15. }
  16. while (--count > 0)
  17. {
  18. cur1 = cur2;
  19. cur2 = cur2->next;
  20. }
  21. tmp = cur2;
  22. printf("%d ", tmp->data);
  23. cur1->next = cur2->next;
  24. cur2 = cur2->next;
  25. free(tmp);
  26. tmp = NULL;
  27. }
  28. }
  29. else
  30. {
  31. return;
  32. }
  33. }
14、寻找链表的中间结点,要求只能遍历一次链表:用两个指针同时指向链表首部,利用循环,快指针一次走两步,慢指针一次走一步,直到快的指针走到链表尾部,此时慢的指针指向的结点就是中间结点。
  1. pNode Find_Mid_Node(pList plist)
  2. {
  3. pList fast = plist;
  4. pList slow = plist;
  5. while (fast != NULL&&fast->next != NULL)
  6. {
  7. fast = fast->next->next;
  8. slow = slow->next;
  9. }
  10. printf("中间结点为:%d\n", slow->data);
  11. return slow;
  12. }
15、对链表进行冒泡排序。
  1. void BubbleSort(pList plist)
  2. {
  3. pList cur = plist;
  4. if (plist == NULL || plist->next == NULL)
  5. {
  6. return;
  7. }
  8. for (; cur->next != NULL; cur = cur->next)
  9. {
  10. pList pre = plist;
  11. Datatype tmp = 0;
  12. for (pre ; pre->next != NULL; pre = pre->next)
  13. {
  14. if (pre->data > pre->next->data)
  15. {
  16. tmp=pre->data;
  17. pre->data = pre->next->data;
  18. pre->next->data = tmp;
  19. }
  20. }
  21. }
  22. }
16、删除倒数第k个元素:两个指针,快的指针先遍历k个结点,然后快慢指针同时走,每次遍历一个结点,知道快指针走到链表尾部,此时慢指针指向的结点就是倒数第k个结点。
  1. void Del_K_Node(pList plist, int k)
  2. {
  3. pList cur1 = plist;
  4. pList cur2 = plist;
  5. int count = k;
  6. if (k == 1)
  7. {
  8. cur1 = cur1->next;
  9. while (cur1->next != NULL)
  10. {
  11. cur1 = cur1->next;
  12. cur2 = cur2->next;
  13. }
  14. cur2->next = NULL;
  15. free(cur1);
  16. cur1 = NULL;
  17. }
  18. else if (k >= 2)
  19. {
  20. while (--count)
  21. {
  22. cur1 = cur1->next;
  23. }
  24. pList tmp = NULL;
  25. while (cur1->next != NULL)
  26. {
  27. cur1 = cur1->next;
  28. cur2 = cur2->next;
  29. }
  30. tmp = cur2->next;
  31. cur2->data = tmp->data;
  32. cur2->next = tmp->next;
  33. free(tmp);
  34. tmp = NULL;
  35. }
  36. else
  37. {
  38. return;
  39. }
  40. }
17、判断链表是否带环:两个指针,快指针每次走两步,慢指针每次走一步,当两个指针相遇,说明链表带环,否则,链表不带环。
  1. pNode Check_Cycle(pList plist)
  2. {
  3. pList fast = plist;
  4. pList slow = plist;
  5. while ((fast != NULL) && (fast->next != NULL))
  6. {
  7. fast = fast->next->next;
  8. slow = slow->next;
  9. if (fast == slow)
  10. {
  11. return fast;
  12. }
  13. }
  14. return NULL;
  15. }
18、求带环链表的入口点(此问题后续详解)。
  1. pNode Get_Circle_Entry_Node(pNode meet, pList plist)
  2. {
  3. assert(meet != NULL);
  4. assert(plist != NULL);
  5. pList cur = plist;
  6. pNode node = meet;
  7. while (cur != node)
  8. {
  9. cur = cur->next;
  10. node = node->next;
  11. }
  12. return cur;
  13. }
19、求带环链表的长度。
  1. int Get_Circle_Length(pNode meet)
  2. {
  3. pNode node = meet;
  4. Datatype count = 1;
  5. meet = meet->next;
  6. while (meet != node)
  7. {
  8. meet = meet->next;
  9. count += 1;
  10. }
  11. return count;
  12. }
20、判断两个不带环链表是否相交:只需判断两条链表的尾结点是否相同即可。
  1. pNode Check_Cross(pList plist1, pList plist2)
  2. {
  3. assert(plist1 != NULL);
  4. assert(plist2 != NULL);
  5. pList cur1 = plist1;
  6. pList cur2 = plist2;
  7. while (cur1->next != NULL)
  8. {
  9. cur1 = cur1->next;
  10. }
  11. while (cur2->next != NULL)
  12. {
  13. cur2 = cur2->next;
  14. }
  15. if (cur1 == cur2)
  16. {
  17. return cur1;
  18. }
  19. else
  20. {
  21. return NULL;
  22. }
  23. }
21、求两个相交不带环链表的交点:将其中一条链表构成环,即就成了求环入口点问题。
  1. pNode Check_Cross_Meet(pList plist1, pList plist2)
  2. {
  3. pList cur1 = plist1;
  4. pList cur2 = plist2;
  5. pNode meet = NULL;
  6. pNode pre = NULL;
  7. pNode node = Check_Cross(plist1, plist2);//判断两条链表是否相交
  8. if (node == NULL)
  9. {
  10. return NULL;
  11. }
  12. node->next = cur1;//将其中一条链表的尾节点接到头结点,构成一个环
  13. meet = Check_Cycle(plist2);//判断链表2是否已经带环
  14. pre = Get_Circle_Entry_Node(meet, plist2);//求出环的入口点
  15. node->next = NULL;//将环拆开
  16. return pre;
  17. }
三、完整代码如下:
Linklist.h
  1. #ifndef __LINK_LIST_H__
  2. #define __LINK_LIST_H__
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <assert.h>
  7. typedef int Datatype;
  8. typedef struct Node
  9. {
  10. Datatype data;
  11. struct Node *next;
  12. }node_t,*pList,*pNode;
  13. void Initlist(pList* plist);//初始化
  14. void Display(pList plist);//打印链表
  15. void Pushfront(pList* plist, Datatype data);//头插
  16. void Popfront(pList* plist);//头删
  17. void Pushback(pList* plist, Datatype data);//尾插
  18. void Popback(pList* plist);//尾删
  19. void Destroy(pList* plist);//销毁链表
  20. pNode Find(pList plist, Datatype data);//查找某个节点
  21. void Invert_list(pList* plist);//链表的逆序
  22. void Invert_display(pList plist);//链表的逆序打印
  23. void Del_Not_Tail(pNode pos);//删除一个非尾节点
  24. void Insert_Front_Node(pNode pos,Datatype data);//在指定位置前插入一个节点
  25. pList Merge(pList* plist1, pList* plist2);//合并链表
  26. void JosephCycle(pList plist,int k);//约瑟夫环
  27. pNode Find_Mid_Node(pList plist);//寻找链表的中间节点,只能遍历一遍链表
  28. void BubbleSort(pList plist);//链表进行冒泡排序
  29. void Del_K_Node(pList plist, int k);//删除倒数第k个元素
  30. pNode Check_Cycle(pList plist);//判断链表是否有环
  31. pNode Get_Circle_Entry_Node(pNode meet, pList plist);//求带环链表的环入口点
  32. int Get_Circle_Length(pNode meet);//求带环链表长度
  33. pNode Check_Cross(pList plist1,pList plist2);//判断两个不带环的链表是否相交
  34. pNode Check_Cross_Meet(pList plist1, pList plist2);//求两个相交不带环链表的交点
  35. #endif

Linklist.c
  1. #include "Linklist.h"
  2. //链表的初始化
  3. void Initlist(pList* plist)
  4. {
  5. plist = NULL;
  6. }
  7. //打印链表
  8. void Display(pList plist)
  9. {
  10. pList cur = plist;
  11. for (; cur != NULL; cur = cur->next)
  12. {
  13. printf("%d--->", cur->data);
  14. }
  15. printf("over\n");
  16. }
  17. //头插
  18. void Pushfront(pList* plist, Datatype data)
  19. {
  20. assert(plist != NULL);
  21. pNode p = NULL;
  22. p =(pNode) malloc(sizeof(node_t));
  23. if (p == NULL)
  24. {
  25. perror("malloc()");
  26. exit(EXIT_FAILURE);
  27. }
  28. p->data = data;
  29. p->next = NULL;
  30. p->next = *plist;
  31. *plist = p;
  32. }
  33. //头删
  34. void Popfront(pList* plist)
  35. {
  36. assert(plist != NULL);
  37. pList cur = *plist;
  38. if (cur == NULL)
  39. {
  40. return;
  41. }
  42. else
  43. {
  44. *plist = cur->next;
  45. free(cur);
  46. cur->next = NULL;
  47. }
  48. }
  49. //尾插
  50. void Pushback(pList* plist,Datatype data)
  51. {
  52. assert(plist != NULL);
  53. pNode cur = *plist;
  54. pNode p = NULL;
  55. p =(pNode) malloc(sizeof(node_t));
  56. if (p == NULL)
  57. {
  58. perror("malloc()");
  59. exit(EXIT_FAILURE);
  60. }
  61. memset(p, 0, sizeof(node_t));
  62. p->data = data;
  63. if (cur == NULL)
  64. {
  65. *plist = p;
  66. }
  67. else
  68. {
  69. while (cur->next)
  70. {
  71. cur = cur->next;
  72. }
  73. cur->next = p;
  74. }
  75. }
  76. //尾删
  77. void Popback(pList* plist)
  78. {
  79. assert(plist != NULL);
  80. pList fast = *plist;
  81. pList slow = NULL;
  82. if (*plist == NULL)
  83. {
  84. return;
  85. }
  86. while (fast!=NULL)
  87. {
  88. slow = fast;
  89. fast = fast->next;
  90. }
  91. if (slow != NULL)
  92. {
  93. slow->next = NULL;
  94. free(fast);
  95. }
  96. else
  97. {
  98. free(fast);
  99. *plist = NULL;
  100. }
  101. }
  102. //销毁链表
  103. void Destroy(pList* plist)
  104. {
  105. assert(plist != NULL);
  106. pList cur = NULL;
  107. while (*plist)
  108. {
  109. cur = (*plist)->next;
  110. free(*plist);
  111. *plist = NULL;
  112. *plist = cur;
  113. }
  114. }
  115. //查找某个结点
  116. pNode Find(pList plist, Datatype data)
  117. {
  118. pNode cur =plist;
  119. while (cur)
  120. {
  121. if (cur->data == data)
  122. {
  123. return cur;
  124. }
  125. cur = cur->next;
  126. }
  127. return NULL;
  128. }
  129. //链表的逆序
  130. void Invert_list(pList *plist)
  131. {
  132. if (((*plist) == NULL) || ((*plist)->next == NULL))
  133. {
  134. return;
  135. }
  136. else
  137. {
  138. pList cur1 = *plist;
  139. pList cur2 = (*plist)->next;
  140. pList cur3 = (*plist)->next->next;
  141. pList tmp = NULL;
  142. while (1)
  143. {
  144. cur2->next = cur1;
  145. cur1->next = tmp;
  146. tmp = cur1;
  147. if (cur3 == NULL)
  148. {
  149. break;
  150. }
  151. else
  152. {
  153. cur1 = cur2;
  154. cur2 = cur3;
  155. cur3 = cur3->next;
  156. }
  157. }
  158. *plist = cur2;
  159. }
  160. }
  161. //链表的逆序打印
  162. void Invert_display(pList plist)
  163. {
  164. if(plist!=NULL)
  165. {
  166. Invert_display(plist->next);
  167. printf("%d--->", plist->data);
  168. }
  169. else
  170. {
  171. return;
  172. }
  173. }
  174. //删除一个非尾结点
  175. void Del_Not_Tail(pNode pos)
  176. {
  177. assert(pos != NULL);
  178. pNode cur = pos->next;
  179. if (cur != NULL)
  180. {
  181. pos->next = cur->next;
  182. pos->data = cur->data;
  183. }
  184. else
  185. {
  186. return;
  187. }
  188. free(cur);
  189. cur = NULL;
  190. }
  191. //在指定位置前插入一个结点
  192. void Insert_Front_Node(pNode pos, Datatype data)
  193. {
  194. assert(pos != NULL);
  195. pNode p = NULL;
  196. p = (pNode)malloc(sizeof(node_t));
  197. if (p == NULL)
  198. {
  199. perror("malloc()");
  200. exit(EXIT_FAILURE);
  201. }
  202. p->next = pos->next;
  203. p->data = pos->data;
  204. pos->data = data;
  205. pos->next = p;
  206. }
  207. //合并有序链表
  208. pList Merge(pList* plist1, pList* plist2)
  209. {
  210. assert(plist1 != NULL);
  211. assert(plist2 != NULL);
  212. pList head = NULL;
  213. pList p = NULL;
  214. pList cur1 = *plist1;
  215. pList cur2 = *plist2;
  216. if (cur1->data < cur2->data)
  217. {
  218. head = cur1;
  219. cur1 = cur1->next;
  220. }
  221. else
  222. {
  223. head = cur2;
  224. cur2 = cur2->next;
  225. }
  226. p = head;
  227. while ((cur1 != NULL) && (cur2 != NULL))
  228. {
  229. if (cur1->data < cur2->data)
  230. {
  231. p->next = cur1;
  232. cur1 = cur1->next;
  233. }
  234. else
  235. {
  236. p->next = cur2;
  237. cur2 = cur2->next;
  238. }
  239. p = p->next;
  240. }
  241. if (cur1 == NULL)
  242. {
  243. p->next = cur2;
  244. }
  245. else if (cur2 == NULL)
  246. {
  247. p->next = cur1;
  248. }
  249. return head;
  250. }
  251. //约瑟夫环
  252. void JosephCycle(pList plist, int k)
  253. {
  254. pList cur1 = plist;
  255. pList cur2 = plist;
  256. if (k >= 2)
  257. {
  258. while (1)
  259. {
  260. int count = k;
  261. pNode tmp = NULL;
  262. if (cur1 == cur1->next)
  263. {
  264. printf("%d\n", cur1->data);
  265. break;
  266. }
  267. while (--count > 0)
  268. {
  269. cur1 = cur2;
  270. cur2 = cur2->next;
  271. }
  272. tmp = cur2;
  273. printf("%d ", tmp->data);
  274. cur1->next = cur2->next;
  275. cur2 = cur2->next;
  276. free(tmp);
  277. tmp = NULL;
  278. }
  279. }
  280. else
  281. {
  282. return;
  283. }
  284. }
  285. //寻找链表的中间结点,只遍历一次链表
  286. pNode Find_Mid_Node(pList plist)
  287. {
  288. pList fast = plist;
  289. pList slow = plist;
  290. while (fast != NULL&&fast->next != NULL)
  291. {
  292. fast = fast->next->next;
  293. slow = slow->next;
  294. }
  295. printf("中间结点为:%d\n", slow->data);
  296. return slow;
  297. }
  298. //链表进行冒泡排序
  299. void BubbleSort(pList plist)
  300. {
  301. pList cur = plist;
  302. if (plist == NULL || plist->next == NULL)
  303. {
  304. return;
  305. }
  306. for (; cur->next != NULL; cur = cur->next)
  307. {
  308. pList pre = plist;
  309. Datatype tmp = 0;
  310. for (pre ; pre->next != NULL; pre = pre->next)
  311. {
  312. if (pre->data > pre->next->data)
  313. {
  314. tmp=pre->data;
  315. pre->data = pre->next->data;
  316. pre->next->data = tmp;
  317. }
  318. }
  319. }
  320. }
  321. //删除倒数第k个元素
  322. void Del_K_Node(pList plist, int k)
  323. {
  324. pList cur1 = plist;
  325. pList cur2 = plist;
  326. int count = k;
  327. if (k == 1)
  328. {
  329. cur1 = cur1->next;
  330. while (cur1->next != NULL)
  331. {
  332. cur1 = cur1->next;
  333. cur2 = cur2->next;
  334. }
  335. cur2->next = NULL;
  336. free(cur1);
  337. cur1 = NULL;
  338. }
  339. else if (k >= 2)
  340. {
  341. while (--count)
  342. {
  343. cur1 = cur1->next;
  344. }
  345. pList tmp = NULL;
  346. while (cur1->next != NULL)
  347. {
  348. cur1 = cur1->next;
  349. cur2 = cur2->next;
  350. }
  351. tmp = cur2->next;
  352. cur2->data = tmp->data;
  353. cur2->next = tmp->next;
  354. free(tmp);
  355. tmp = NULL;
  356. }
  357. else
  358. {
  359. return;
  360. }
  361. }
  362. //判断链表是否带环
  363. pNode Check_Cycle(pList plist)
  364. {
  365. pList fast = plist;
  366. pList slow = plist;
  367. while ((fast != NULL) && (fast->next != NULL))
  368. {
  369. fast = fast->next->next;
  370. slow = slow->next;
  371. if (fast == slow)
  372. {
  373. return fast;
  374. }
  375. }
  376. return NULL;
  377. }
  378. //求带环链表的环入口点
  379. pNode Get_Circle_Entry_Node(pNode meet, pList plist)
  380. {
  381. assert(meet != NULL);
  382. assert(plist != NULL);
  383. pList cur = plist;
  384. pNode node = meet;
  385. while (cur != node)
  386. {
  387. cur = cur->next;
  388. node = node->next;
  389. }
  390. return cur;
  391. }
  392. //求带环链表的长度
  393. int Get_Circle_Length(pNode meet)
  394. {
  395. pNode node = meet;
  396. Datatype count = 1;
  397. meet = meet->next;
  398. while (meet != node)
  399. {
  400. meet = meet->next;
  401. count += 1;
  402. }
  403. return count;
  404. }
  405. //判断两个不带环链表是否相交
  406. pNode Check_Cross(pList plist1, pList plist2)
  407. {
  408. assert(plist1 != NULL);
  409. assert(plist2 != NULL);
  410. pList cur1 = plist1;
  411. pList cur2 = plist2;
  412. while (cur1->next != NULL)
  413. {
  414. cur1 = cur1->next;
  415. }
  416. while (cur2->next != NULL)
  417. {
  418. cur2 = cur2->next;
  419. }
  420. if (cur1 == cur2)
  421. {
  422. return cur1;
  423. }
  424. else
  425. {
  426. return NULL;
  427. }
  428. }
  429. //求两个相交不带环链表的交点
  430. pNode Check_Cross_Meet(pList plist1, pList plist2)
  431. {
  432. pList cur1 = plist1;
  433. pList cur2 = plist2;
  434. pNode meet = NULL;
  435. pNode pre = NULL;
  436. pNode node = Check_Cross(plist1, plist2);//判断两条链表是否相交
  437. if (node == NULL)
  438. {
  439. return NULL;
  440. }
  441. node->next = cur1;//将其中一条链表的尾节点接到头结点,构成一个环
  442. meet = Check_Cycle(plist2);//判断链表2是否已经带环
  443. pre = Get_Circle_Entry_Node(meet, plist2);//求出环的入口点
  444. node->next = NULL;//将环拆开
  445. return pre;
  446. }

test.c
  1. #include "Linklist.h"
  2. void test1()//头插 头删 销毁
  3. {
  4. pList plist = NULL;
  5. Initlist(&plist);
  6. Pushfront(&plist, 1);
  7. Pushfront(&plist, 2);
  8. Pushfront(&plist, 3);
  9. Pushfront(&plist, 4);
  10. Pushfront(&plist, 5);
  11. Display(plist);
  12. Destroy(&plist);
  13. Display(plist);
  14. /*Popfront(&plist);
  15. Display(plist);
  16. Popfront(&plist);
  17. Display(plist);
  18. Popfront(&plist);
  19. Display(plist);
  20. Popfront(&plist);
  21. Display(plist);
  22. Popfront(&plist);
  23. Display(plist);*/
  24. }
  25. void test2()//尾插 尾删
  26. {
  27. pList plist = NULL;
  28. Initlist(&plist);
  29. Pushback(&plist, 1);
  30. Pushback(&plist, 2);
  31. Pushback(&plist, 3);
  32. Pushback(&plist, 4);
  33. Pushback(&plist, 5);
  34. Display(plist);
  35. Popback(&plist);
  36. Display(plist);
  37. Popback(&plist);
  38. Display(plist);
  39. Popback(&plist);
  40. Display(plist);
  41. Popback(&plist);
  42. Display(plist);
  43. Popback(&plist);
  44. Display(plist);
  45. }
  46. void test3() //查找 逆序 逆序打印
  47. {
  48. pList plist = NULL;
  49. Initlist(&plist);
  50. Pushfront(&plist, 1);
  51. Pushfront(&plist, 2);
  52. Pushfront(&plist, 3);
  53. Pushfront(&plist, 4);
  54. Pushfront(&plist, 5);
  55. Display(plist);
  56. pNode ret=Find(plist,6);
  57. printf("%d\n", ret->data);
  58. Invert_list(&plist);
  59. Display(plist);
  60. Invert_display(plist);
  61. }
  62. void test4() //删除一个非尾结点
  63. {
  64. pList plist = NULL;
  65. pNode pnode = NULL;
  66. Initlist(&plist);
  67. Pushfront(&plist, 1);
  68. Pushfront(&plist, 2);
  69. Pushfront(&plist, 3);
  70. Pushfront(&plist, 4);
  71. Pushfront(&plist, 5);
  72. Display(plist);
  73. pnode = Find(plist, 4);
  74. Del_Not_Tail(pnode);
  75. Display(plist);
  76. }
  77. void test5() //在指定位置前增加一个结点
  78. {
  79. pList plist = NULL;
  80. pNode pnode = NULL;
  81. Initlist(&plist);
  82. Pushfront(&plist, 1);
  83. Pushfront(&plist, 2);
  84. //Pushfront(&plist, 3);
  85. Pushfront(&plist, 4);
  86. Pushfront(&plist, 5);
  87. Display(plist);
  88. pnode = Find(plist,2);
  89. Insert_Front_Node(pnode, 3);
  90. Display(plist);
  91. }
  92. void test6() //合并有序链表
  93. {
  94. pList plist1 = NULL;
  95. pList plist2 = NULL;
  96. pList head = NULL;
  97. Initlist(&plist1);
  98. Initlist(&plist2);
  99. Pushfront(&plist1, 10);
  100. Pushfront(&plist2, 9);
  101. Pushfront(&plist1, 8);
  102. Pushfront(&plist2, 7);
  103. Pushfront(&plist1, 6);
  104. Pushfront(&plist2, 5);
  105. Pushfront(&plist1, 4);
  106. Pushfront(&plist2, 3);
  107. Pushfront(&plist1, 2);
  108. Pushfront(&plist2, 1);
  109. Display(plist1);
  110. Display(plist2);
  111. head=Merge(&plist1, &plist2);
  112. Display(head);
  113. Display(plist1);
  114. Display(plist2);
  115. }
  116. void test7() //约瑟夫环
  117. {
  118. pList plist = NULL;
  119. Initlist(&plist);
  120. Pushfront(&plist, 10);
  121. Pushfront(&plist,9);
  122. Pushfront(&plist, 8);
  123. Pushfront(&plist, 7);
  124. Pushfront(&plist, 6);
  125. Pushfront(&plist, 5);
  126. Pushfront(&plist, 4);
  127. Pushfront(&plist, 3);
  128. Pushfront(&plist, 2);
  129. Pushfront(&plist, 1);
  130. Display(plist);
  131. Find(plist, 10)->next = plist;
  132. JosephCycle(plist,1);
  133. }
  134. void test8() //寻找链表的中间结点,只遍历一次链表
  135. {
  136. pList plist = NULL;
  137. pNode pnode = NULL;
  138. Initlist(&plist);
  139. Pushfront(&plist, 10);
  140. Pushfront(&plist, 9);
  141. Pushfront(&plist, 8);
  142. Pushfront(&plist, 7);
  143. Pushfront(&plist, 6);
  144. Pushfront(&plist, 5);
  145. Pushfront(&plist, 4);
  146. Pushfront(&plist, 3);
  147. Pushfront(&plist, 2);
  148. Pushfront(&plist, 1);
  149. Display(plist);
  150. pnode=Find_Mid_Node(plist);
  151. }
  152. void test9() //链表进行冒泡排序
  153. {
  154. pList plist = NULL;
  155. Initlist(&plist);
  156. Pushfront(&plist, 9);
  157. Pushfront(&plist, 5);
  158. Pushfront(&plist, 2);
  159. Pushfront(&plist, 6);
  160. Pushfront(&plist, 8);
  161. Pushfront(&plist, 1);
  162. Pushfront(&plist, 4);
  163. Pushfront(&plist, 7);
  164. Pushfront(&plist, 10);
  165. Pushfront(&plist, 3);
  166. Display(plist);
  167. BubbleSort(plist);
  168. Display(plist);
  169. }
  170. void test10() //删除倒数第k个元素
  171. {
  172. pList plist = NULL;
  173. Initlist(&plist);
  174. Pushfront(&plist, 10);
  175. Pushfront(&plist, 9);
  176. Pushfront(&plist, 8);
  177. Pushfront(&plist, 7);
  178. Pushfront(&plist, 6);
  179. Pushfront(&plist, 5);
  180. Pushfront(&plist, 4);
  181. Pushfront(&plist, 3);
  182. Pushfront(&plist, 2);
  183. Pushfront(&plist, 1);
  184. Display(plist);
  185. Del_K_Node(plist,1);
  186. Display(plist);
  187. }
  188. void test11() //判断链表是否带环 求带环链表的环入口点 求带环链表的长度
  189. {
  190. pList plist = NULL;
  191. pNode meet = NULL;
  192. pNode entry = NULL;
  193. int ret = 0;
  194. Initlist(&plist);
  195. Pushfront(&plist, 10);
  196. Pushfront(&plist, 9);
  197. Pushfront(&plist, 8);
  198. Pushfront(&plist, 7);
  199. Pushfront(&plist, 6);
  200. Pushfront(&plist, 5);
  201. Pushfront(&plist, 4);
  202. Pushfront(&plist, 3);
  203. Pushfront(&plist, 2);
  204. Pushfront(&plist, 1);
  205. Display(plist);
  206. Find(plist, 10)->next = Find(plist,5);
  207. meet=Check_Cycle(plist);
  208. //printf("%d\n", ret);
  209. entry = Get_Circle_Entry_Node(meet, plist);
  210. printf("环入口点为:%d\n", entry->data);
  211. ret = Get_Circle_Length(meet);
  212. printf("链表长度为:%d\n", ret);
  213. }
  214. void test12() //判断两个不带环链表是否相交 求两个相交的不带环链表的交点
  215. {
  216. pList plist1 = NULL;
  217. pList plist2 = NULL;
  218. pNode node = NULL;
  219. pNode meet = NULL;
  220. Initlist(&plist1);
  221. Initlist(&plist2);
  222. Pushfront(&plist1, 10);
  223. Pushfront(&plist1, 9);
  224. Pushfront(&plist1, 8);
  225. Pushfront(&plist1, 7);
  226. Pushfront(&plist1, 6);
  227. Pushfront(&plist1, 4);
  228. Pushfront(&plist1, 2);
  229. Display(plist1);
  230. Pushfront(&plist2, 5);
  231. Pushfront(&plist2, 4);
  232. Pushfront(&plist2, 3);
  233. Pushfront(&plist2, 2);
  234. Pushfront(&plist2, 1);
  235. Display(plist2);
  236. Find(plist2, 5)->next = Find(plist1, 6);
  237. Display(plist1);
  238. Display(plist2);
  239. node=Check_Cross(plist1, plist2);
  240. meet = Check_Cross_Meet(plist1, plist2);
  241. printf("交点为:%d\n", meet->data);
  242. }
  243. int main()
  244. {
  245. test12();
  246. return 0;
  247. }
























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

闽ICP备14008679号