zoukankan      html  css  js  c++  java
  • 递归反转单链表

    递归反转

    本文介绍递归反转单链表,和之前的循环遍历反转单链表方式略有不同,递归的方式要写出推到递归公式。并且在递归的同时修改指针的指向。
    先定义Node节点

    class Node
    {
    public:
        Node(int dt, Node *nt = nullptr) : data(dt), next(nt) {}
        Node() = default;
        int data;
        Node *next;
    };
    

    Node节点构成的链表如下图
    https://cdn.llfc.club/1641544598%281%29.jpg

    基本思路是实现recursive_reverse函数

    Node* recursive_reverse(Node* p){
        //判断p为空或者是单节点直接返回
        if(p == nullptr || p->next==nullptr){
            return ;
        }
    
        //递归查找,直到返回队尾元素作为头节点
        //否则继续递归处理下一个节点
        auto nextnode = recursive_reverse(p->next);
        return nextnode;
    }
    

    上述代码最终会将链表的尾节点返回。但是我们没有完成链表的逆转,需要改变链表节点Node的next指针。
    假设有两个节点
    https://cdn.llfc.club/1641545121%281%29.jpg
    node1节点为p节点
    p->next指向的就是node2节点
    p->next->next指向的就是末尾的空指针。
    所以当有两个节点的时候我们可以如下操作完成p和p->next两个节点指向的修改,也就是node1和node2两个节点的修改。
    我们将p->next->next = p->next 就是将node2的next指向了node1.
    我们将p->next = nullptr 就是将node1->next指向了空地址。所以node1此时变为尾节点。
    而之前的递归保证了最后返回的是node2节点,此时node2节点就作为头节点,从而完成了逆转。
    图解为下图
    https://cdn.llfc.club/1641545895.jpg
    这是两个节点的情况,如果是三个节点呢,那就依次类推,依次完成node3->next指向node2,node2->next指向node1,node1->next指向空地址。
    所以n>=2的情况都是和两个节点类似的,那么我们补全recursive_reverse函数

    Node *recursive_reverse(Node *p)
    {
        //如果链表为空或者为单节点,直接返回
        if (p == nullptr || p->next == nullptr)
        {
            return p;
        }
        //否则继续递归处理下一个节点
        auto nextnode = recursive_reverse(p->next);
        //改变p的下一个节点next指向,链表逆转
        p->next->next = p;
        //改变p的next指向
        p->next = nullptr;
        return nextnode;
    }
    

    接下来我们实现一个创建链表的函数用来测试

    Node *createList()
    {
        auto node1 = new Node(1);
        auto node2 = new Node(2);
        auto node3 = new Node(3);
        node1->next = node2;
        node2->next = node3;
        return node1;
    }
    

    然后实现销毁链表回收内存的函数

    void delocateList(Node *p)
    {
        while (p != nullptr)
        {
            auto temp = p;
            p = p->next;
            delete temp;
        }
    }
    

    然后实现打印节点的函数

    void printList(Node *p)
    {
        while (p != nullptr)
        {
            cout << p->data << " -> ";
            p = p->next;
        }
    
        cout << " nullptr " << endl;
    }
    

    最后我们在main函数中测试

        auto list = createList();
        printList(list);
        list = recursive_reverse(list);
        printList(list);
        delocateList(list);
    

    程序输出如下

    1 -> 2 -> 3 ->  nullptr
    3 -> 2 -> 1 ->  nullptr
    

    可以看到链表被逆转了。
    源码链接https://gitee.com/secondtonone1/algorithms
    我的公众号,谢谢关注
    https://cdn.llfc.club/gzh.jpg

    重剑无锋,大巧不工
  • 相关阅读:
    poj3481
    查找湖南问题
    tyvj1033
    tyvj1088
    oil倒油
    加分二叉树
    模拟题2
    模拟题3
    Free pascal中的random函数
    Spring MVC入门配置
  • 原文地址:https://www.cnblogs.com/secondtonone1/p/15775890.html
Copyright © 2011-2022 走看看