• 【单链表】实现链表逆置


    目录

    一、思想

    1.非递归实现

    2.递归思想

    二、代码讲解

    1.非递归

    代码(C语言实现)

    运行结果

    2.递归代码(C++实现)

    执行结果

    三、力扣206题(C语言实现)

    非递归实现代码

    执行结果


    一、思想

    1.非递归实现

    将原链表断开,然后把头结点的下一个结点位置的值依次进行头插在头结点后面,用下图示例:

    1.首先把plist断开:plist->next=NULL;

    p=plist->next; q=plist->next;

    2.把p头插在plist链后面:

    p=plist->next; //p=NULL

    plist->next=p; //plist->next=500,500是p结点的地址

    3.把p重新赋值为q的位置,q后移一个:p=q;  q=p->next;

    把p继续进行头插到plist后面:p->next=plist->next; plist->next=p; 

    重复操作,一直到最后q=NULL,p=q=NULL时停下。

    2.递归思想

            假设是6个节点,节点1调用节点2,节点2调用节点3,....,节点5调用节点6。逆置的思想是把1->2->3->4->5->6改为1<-2<-3<-4<-5<-6,需要把节点的指向颠倒,代码实现就是p->next->next=p (递推的时候5->next=6,回归的时候6->next=5,因此,5->next->next=5)然后断开原来的指向p->next=NULL,避免形成环。

     

     其代码就是:
    Node* Reverse(Node* head)
    {
        if (head->m_next == NULL)
            return head;//一直往下递归找到head(6)
        Node* newhead = Reverse(head->next); //递推返回head(6),newhead=head(6)
        head->next->next = head;//head=head(5)
        head->next = NULL;
        return newhead;
    }

    二、代码讲解

    1.非递归

    1.栈实现:让链表依次进栈、再依次出栈赋值给链表,时间复杂度:O(n),空间O(n)

    2.链表实现:将头结点和下一个结点断开,头插法,从后向前遍历插入。

    空链表、0个结点和1个结点不需要逆置

    代码(C语言实现)

    1. //实现链表逆置
    2. #include
    3. #include
    4. #include
    5. typedef struct Node
    6. {
    7. int data;
    8. struct Node* next;
    9. }Node, * List;
    10. //初始化
    11. void InitList(List plist)
    12. {
    13. assert(plist != NULL);
    14. if (plist == NULL)
    15. {
    16. return;
    17. }
    18. //plist->data;//头节点的data不使用
    19. plist->next = NULL;
    20. }
    21. //尾插
    22. bool Insert_tail(List plist, int val)
    23. {
    24. assert(plist != NULL);
    25. if (plist == NULL)
    26. {
    27. return false;
    28. }
    29. //申请结点
    30. Node* p = (Node*)malloc(sizeof(Node));
    31. assert(p != NULL);
    32. //将数据val放入到新结点;
    33. p->data = val;
    34. //找尾巴
    35. Node* q;
    36. for (q = plist; q->next != NULL; q = q->next)
    37. {
    38. ;
    39. }
    40. //插入新结点,把p插入到q的后面
    41. p->next = q->next;//p->next=NULL;
    42. q->next = p;
    43. return true;
    44. }
    45. //输出
    46. void Show(List plist)
    47. {
    48. assert(plist != NULL);
    49. if (plist == NULL)
    50. {
    51. return;
    52. }
    53. for (Node* p = plist->next; p != NULL; p = p->next)
    54. {
    55. printf("%d ", p->data);
    56. }
    57. printf("\n");
    58. }
    59. //链表逆置
    60. void Reverse(List plist)
    61. {
    62. assert(plist != NULL);
    63. //空链表、0个结点和1个结点不需要逆置
    64. if (plist == NULL || plist->next == NULL || plist->next->next == NULL)
    65. {
    66. return;
    67. }
    68. Node* p = plist->next;
    69. Node* q = p->next;
    70. plist->next = NULL;//把链表断开
    71. while (p != NULL)
    72. {
    73. q = p->next;//防止链断
    74. //头插p
    75. p->next = plist->next;
    76. plist->next = p;
    77. p = q;
    78. }
    79. }
    80. int main()
    81. {
    82. Node head;
    83. InitList(&head);
    84. for (int i = 0; i < 20; i++)
    85. {
    86. Insert_tail(&head, i);
    87. }
    88. Show(&head);
    89. Reverse(&head);
    90. Show(&head);
    91. }

    运行结果

    2.递归代码(C++实现)

    1. class Node
    2. {
    3. public:
    4. Node(int v) :m_value(v), m_next(NULL) {}
    5. Node() :m_next(NULL) {}
    6. int m_value;
    7. Node* m_next;
    8. };
    9. Node* Reverse(Node* head)
    10. {
    11. if (head->m_next == NULL)
    12. return head;
    13. Node* newhead = Reverse(head->m_next);
    14. head->m_next->m_next = head;
    15. head->m_next = NULL;
    16. return newhead;
    17. }
    18. void Print(Node* head)
    19. {
    20. Node* p = head;
    21. while (p)
    22. {
    23. cout << p->m_value << " ";
    24. p = p->m_next;
    25. }
    26. cout << endl;
    27. }
    28. void main()
    29. {
    30. Node* head = NULL;
    31. Node a(1), b(2), c(3), d(4), e(5), f(6);
    32. head = &a;
    33. a.m_next = &b;
    34. b.m_next = &c;
    35. c.m_next = &d;
    36. d.m_next = &e;
    37. e.m_next = &f;
    38. Print(head);
    39. head = Reverse(head);
    40. Print(head);
    41. }

    执行结果

     

    三、力扣206题(C语言实现)

    非递归实现代码

    1. struct ListNode* reverseList(struct ListNode* head){
    2. if(head==NULL)//对[]的情况进行处理
    3. return NULL;
    4. struct ListNode plist;
    5. plist.next=head;//力扣的链表都不带头节点,自定义一个头结点:plist
    6. //struct ListNode *p=plist.next; head->p //慢指针
    7. struct ListNode*q;
    8. q=head->next;//快指针
    9. plist.next=NULL;//链表断开
    10. //p头插到plist后
    11. while(head!=NULL)
    12. {
    13. q=head->next;
    14. head->next=plist.next;
    15. plist.next=head;
    16. head=q;
    17. }
    18. return plist.next;//返回head
    19. }

    执行结果

  • 相关阅读:
    .NET Core 中插件式开发实现
    苏三说:今年测试行业企业招聘的真相
    C和指针 第15章 输入/输出函数 15.14 流错误函数
    (利用IDEA+Maven)定制属于自己的jar包
    基于VUE+Node实现MapReduce的分布式计算系统
    5. Mongodb 面试题
    [云原生案例2.2 ] Kubernetes的部署安装 【单master集群架构 ---- (二进制安装部署)】网络插件部分
    vue3使用Swiper实现简单轮播图
    线性回归详解
    换个方式认识一下——微信公众号搜索公众号列表 API
  • 原文地址:https://blog.csdn.net/qq_53830608/article/details/127674482