• 数据结构之链表


    目录

    1.链表的定义,优劣势,基本实现看以往博客;

    2.以下介绍关于链表的特殊操作:


    1.链表的定义,优劣势,基本实现看以往博客;

    2.以下介绍关于链表的特殊操作:

    1)单链表的反向输出:

    实现思想:利用了递归的思想(或者说栈的后进先出的特点)

    实现要点:怎么理解这里的递归,怎么用?递归的结束标志是什么?上代码:

    1. void printReverse(Node* p) {
    2. if (p == NULL) {
    3. return;
    4. }
    5. printReverse(p->next);
    6. printf("%d ", p->data);
    7. }

    这里递归的结束点就是return,向主调返回。具体怎么实现就是这样,通过先递归后输出就可以实现从后往前输出;

    2)单链表的反转:

    实现思想:找到前面的结点和后面的结点,让后面的结点连接前面的结点,确保后面的后面的结点不丢失,所以还需要一个结点记住;

    实现要点:结点反转操作的步骤不能随意改变。上代码:

    1. void reverse() {
    2. if (head == NULL) {
    3. printf("没有链表,还无法反转!");
    4. return;
    5. }
    6. Node* pre = head;
    7. Node* temp = head->next;
    8. Node* tail = temp->next;
    9. pre->next = NULL;
    10. while (temp != NULL) {
    11. tail = temp->next;
    12. temp->next = pre;
    13. pre = temp;
    14. temp = tail;
    15. //上面是让tail一直在temp的后面;
    16. // 两个想法最后达到的效果一样,为什么下面会报错;
    17. //我是想着,三个指针同时动,每次都移动一位;
    18. /*temp->next = pre;
    19. pre = temp;
    20. temp = tail;
    21. if (temp == NULL)
    22. {
    23. break;
    24. }
    25. tail = tail->next;*/
    26. }
    27. head = pre;
    28. }

    上面的注释部分就是一个错误演示:会导致空指针赋值的异常。

    3)单链表的归并排序

    实现思想:主要还是递归。通过每一层函数实现分区的操作,并对两个有序链表地分区进行合并,不断地把一个链表拆分为多个小分区。(这里的分区还是要区别于快速排序的中间值分区)

    实现要点:首先,准备一个函数用来合并两个有序链表。其次,准备中间值分区函数。最后定义排序函数,先上代码:

    1. struct ListNode* findMid(struct ListNode* head);
    2. struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2);
    3. struct ListNode* sortList(struct ListNode* head) {
    4. if(head == NULL||head->next == NULL){
    5. return head;
    6. }
    7. struct ListNode* middle = findMid(head);
    8. struct ListNode* right = middle->next;
    9. middle->next = NULL;
    10. struct ListNode* left = sortList(head);
    11. struct ListNode* sortedRight = sortList(right);
    12. return mergeTwoLists(left,sortedRight);
    13. }
    14. struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    15. //利用递归思想:
    16. //每一层只需要返回一个链表就行了
    17. //上一层只需要 next = 下一层的链表;
    18. if(list1 == NULL){
    19. return list2;
    20. }
    21. if(list2 == NULL){
    22. return list1;
    23. }
    24. if(list1->val<=list2->val){
    25. list1->next = mergeTwoLists(list1->next,list2);
    26. return list1;
    27. }
    28. else{
    29. list2->next = mergeTwoLists(list2->next,list1);
    30. return list2;
    31. }
    32. }
    33. struct ListNode* findMid(struct ListNode* head){
    34. //找中间;
    35. struct ListNode* k = head->next;
    36. struct ListNode* m = head;
    37. while(k && k->next){
    38. m = m->next;
    39. k = k->next->next;
    40. }
    41. return m;
    42. }

    来解释一下代码:

    1.findMid函数就是找到链表中间值,通过快指针“一步两块”,慢指针“一步一块”,当快指针走到null或者,他的next走到null;那么慢指针处就是中间点。

    2.mergeTwoLists函数作用:合并两个有序链表。如果只有单个链表返回就行。如果确实有两个有序链表合并,我们就用递归的思想(这里假设升序),如果list1的数据<=list2的数据,那么,就把list1的结点单独拿出来,再调用函数,参数为list1->next和list2,每一层返回一个链表,最后就输出了.

    3.sort函数其实就是先分区,再合并,但是由于合并操作在最后,所以其实是把链表先分到实在不能再分,然后逐层合并返回.

  • 相关阅读:
    小程序的运行机制
    Spark读取CSV文件(Scala)
    【Python】基础(学习笔记)
    理想汽车×OceanBase:当造车新势力遇上数据库新势力
    预算有限但想改善客户服务?教你几招轻松解决~
    基于邻接矩阵的广度优先遍历
    【强化学习论文合集 | 2021年合集】七. ICRA-2021 强化学习论文
    为Linux内核增加一个系统调用
    深入理解 Netty FastThreadLocal
    深度学习之基于YoloV5安检仪危险品识别系统
  • 原文地址:https://blog.csdn.net/2303_79380171/article/details/137439143