当前位置:   article > 正文

数据结构 --- 有序链表的构建、合并、反转

有序链表

链表的结构体描述

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #include <time.h>
  5. struct Node
  6. {
  7. int data;
  8. struct Node* next;
  9. };
  10. //创建有头链表
  11. struct Node* createList()
  12. {
  13. //动态内存申请
  14. struct Node* headNode = (struct Node*)malloc(sizeof(struct Node));
  15. assert(headNode);
  16. headNode->next = NULL;
  17. return headNode;
  18. }
  19. //创建节点
  20. struct Node* createNode(int data)
  21. {
  22. struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
  23. assert(newNode);
  24. newNode->data = data;
  25. newNode->next = NULL;
  26. return newNode;
  27. }

有序链表的构建

有序链表的构建过程是怎么样的?以上数据依次插入到链表如何形成有序?需要从原链表中找第一次大于要插入元素的位置,如果没有找到就插在链表的后面 (假设从小到大排序)

  1. //要插入的链表 要插入的数据
  2. void push_sort(struct Node* list, int data)
  3. {
  4. //把用户的数据变成一个节点
  5. struct Node* newNode = createNode(data);
  6. //找第一次大于新节点元素的位置以及前驱节点-> 指定位置插入
  7. struct Node* preNode = list;
  8. //当前节点
  9. struct Node* curNode = list->next;
  10. //当前节点不为空 并且当前节点的数据 <= 指定数据
  11. while (curNode != NULL && curNode->data <= data)
  12. {
  13. //接着往下找
  14. preNode = curNode;
  15. curNode = preNode->next;
  16. }
  17. //当前节点为空 preNode == list 代表没有移动一步
  18. if (curNode == NULL && preNode == list)
  19. {
  20. //链表为空直接把新节点插到 list 后面
  21. list->next = newNode;
  22. }
  23. //当前节点为空 preNode != list
  24. else if (curNode == NULL && preNode != list)
  25. {
  26. //没有找到直接放在链表的最后面
  27. preNode->next = newNode;
  28. }
  29. //在中间
  30. else
  31. {
  32. //做插入
  33. preNode->next = newNode;
  34. newNode->next = curNode;
  35. }
  36. }

链表的反转 

法一:

遍历链表,再创建一个链表,采用表头法插入,就实现反转了

法二:

有 3 个指针指向三个位置,只需要改变指针的方向改变即可,最后处理头节点

nextNode:用于保存下一个,断开之前先保存

①把当前节点中的 next 指针指向它的前驱节点

②把 preNode 移到 curNode 的位置,把 curNode 移到 nextNode 的位置,循环重复以上操作,直到最后一个节点

③退出循环时,把 headNode 指向最后一个节点即可

从而实现链表的反转(直接把指针的方向改变)

由于保存了下一个节点,把链表分成多个子链表,一步步把指针反转

每次从原链表中拆一个节点出来把指针反转,重复此操作

①第一个节点的前驱节点等于空

②当前节点等于第一个节点

③当前节点的下一个可以理解为剩下的链表,每次从剩下的链表中拿一个头节点出来,把指针反转,指向前面那个节点,剩下的链表只有一个节点的时候,把 headNode 指向最后一个节点即可

  1. //要反转的链表
  2. void reverse(struct Node* list)
  3. {
  4. //链表为空或者链表只有一个节点,不需要反转
  5. if (list == NULL || list->next == NULL|| list->next->next == NULL)
  6. return;
  7. //第一个节点的前驱节点等于空
  8. struct Node* preNode = NULL;
  9. //当前节点等于第一个节点
  10. struct Node* curNode = list->next;
  11. //当前节点的下一个-> 也就是剩下的链表
  12. //两个节点以上
  13. //剩下的链表从第3个节点开始
  14. struct Node* surList = curNode->next;
  15. //剩下链表不为空
  16. while (surList != NULL)
  17. {
  18. //依次做反转
  19. //当前节点的next指针指向preNode
  20. curNode->next = preNode;
  21. preNode = curNode;
  22. curNode = surList;
  23. surList = curNode->next;
  24. }
  25. //做最后一步的连接
  26. curNode->next = preNode;
  27. list->next = curNode;
  28. }

链表的打印

  1. void printList(struct Node* list)
  2. {
  3. //定义一个移动的指针从第二个节点开始打印
  4. struct Node* pmove = list->next;
  5. //当前节点不为空
  6. while (pmove != NULL)
  7. {
  8. //打印数据
  9. printf("%d\t", pmove->data);
  10. //移到下一个位置
  11. pmove = pmove->next;
  12. }
  13. printf("\n");
  14. }

链表的归并

两个有序链表 1 3 5、2 4 6 做归并,把第二个链表遍历一遍,做一次有序插入

  1. //把第一个链表中的值归并到第二个链表中
  2. void mergeList(struct Node* list1, struct Node* list2)
  3. {
  4. //循环遍历第二个链表
  5. struct Node* pmove = list2->next;
  6. //节点不为空
  7. while (pmove != NULL)
  8. {
  9. //插到list1中 要插入的数据
  10. push_sort(list1, pmove->data);
  11. pmove = pmove->next;
  12. }
  13. }

测试代码

  1. int main()
  2. {
  3. srand((unsigned int)time(NULL));
  4. struct Node* list = createList();
  5. //插入
  6. for (int i = 0; i < 10; i++)
  7. {
  8. push_sort(list, rand() % 100);
  9. }
  10. printList(list);
  11. reverse(list);
  12. printList(list);
  13. //创建两个链表
  14. struct Node* list1=createList();
  15. push_sort(list1, 1);
  16. push_sort(list1, 3);
  17. push_sort(list1, 5);
  18. struct Node* list2 = createList();
  19. push_sort(list2, 2);
  20. push_sort(list2, 4);
  21. push_sort(list2, 6);
  22. mergeList(list1, list2);
  23. printList(list1);
  24. return 0;
  25. }
  26. /* 输出 */
  27. 16 29 42 55 61 64 75 79 83 96
  28. 96 83 79 75 64 61 55 42 29 16
  29. 1 2 3 4 5 6
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/858738
推荐阅读
相关标签
  

闽ICP备14008679号