使用递归实现链表反转

链表反转(图解)



前言

链表反转是面试中的一个高频题目,可以通过多种方法实现,例如循环,递归;本篇文章将使用递归对链表实现反转。

一、链表反转

例如,给定一个单链表,原链表中的数据为: 1–>2–>3–>,反转后的链表为:4–>3–>2–>1。

二、递归思想

递归,有”递“还要有”归“,所谓递归,就是会在函数内部代码中,调用这个函数本身,所以,我们必须要找出递归的结束条件,否则会一直调用自己,造成死循环,从而栈内存溢出。也就是说,我们需要找出当方法的参数符合某一条件时,递归结束,之后把结果返回。使用递归反转其实就是从链表第一个存数据的节点开始,一次递归调用反转每一个节点,直到把最后一个节点反转完毕,整个链表就反转完毕。

三、具体实现

1.反转方法API

public void reverse():对整个链表反转
public void reverse(Node curr):反转链表中的某个节点,并把反转后的节点返回

2.具体实现代码

(链表的实现代码见另一篇文章:链式存储结构–单向链表的实现戳这儿

public void reverse(){
        if (isEmpty()){
            return;
        }
        reverse(head.next);
    }
    public Node reverse(Node curr){
        if (curr.next == null){
            //如果curr是最后一个节点,让头节点指向它
            head.next = curr;
            return curr;
        }
        //递归反转当前节点curr的下一个节点,返回值是链表反转后当前节点的上一个节点
        Node pre = reverse(curr.next);
        //让返回的下一个节点成为当前节点curr
        pre.next = curr;
        //使节点原来的指向为空
        curr.next = null;
        return curr;
    }

3.方法测试

测试结果:
在这里插入图片描述

四、方法调用过程

main方法进栈
在这里插入图片描述

在main方法中调用reverse()方法,reverse()方法进栈。
在这里插入图片描述

reverse() 方法调用带重载的reverse(1) 方法。(此时reverse的参数curr=1,此处简写为reverse(1))reverse(1) 方法进栈,当方法执行到Node pre = reverse(2)时,调用带重载的reverse(2) 方法。
在这里插入图片描述

reverse(2) 方法进栈,当方法执行到Node pre = reverse(3)时,调用带重载的reverse(3) 方法
在这里插入图片描述

reverse(3) 方法进栈,当方法执行到Node pre = reverse(4)时,调用带重载的reverse(4) 方法。
在这里插入图片描述

reverse(4) 方法进栈, 当执行reverse(4) 方法时, 进行判断curr.next == null ,此时满足条件,使头结点指向 4 这个结点 ,然后,该方法将该节点返回给reverse(3).(reverse(4) 执行完毕出栈)
在这里插入图片描述
此时使head节点指向该curr节点,curr = 4;

接下来reverse(3) 接收 reverse(4) 的返回值,此时 当前pre 是4结点 ,执行剩余的代码;
pre.next = curr; 将 4 结点 的下一个结点指向 3 结点;
curr.next = null; 将 3 结点 的下一个结点指向 null (使3 结点原本指向指向4结点的指针断开)
reverse(3) 执行完毕后,将返回值(返回的是3结点)给 reverse(2) , 然后出栈。

在这里插入图片描述
紧接着 reverse(2) 接收 reverse(3) 的返回值 此时 当前pre 是3结点 ,执行剩余代码;
pre.next = curr; 将 3 结点 的下一个结点指向 2 结点;
curr.next = null; 将 2 结点 的下一个结点指向 null; (使2结点原本指向指向3结点的指针断开)
reverse(2) 执行完毕后,将返回值(返回的是2结点)给 reverse(1) , 然后出栈。

在这里插入图片描述
最后reverse(1) 接收 reverse(2) 的返回值 此时pre 是2结点 ,执行剩余的代码;
pre.next = curr; 将 2 结点 的下一个结点指向 1 结点;
curr.next = null; 将 1 结点 的下一个结点指向 null ;(使1结点原本指向指向2结点的指针断开)
reverse(1) 执行完毕后,将返回值(返回的是1结点)给 reverse() 方法(该方法没有使用变量接收返回值 ), 然后出栈

在这里插入图片描述
至此,程序执行完毕,使用递归反转单链表的功能已经实现。

方法调用内存图如下:
在这里插入图片描述

总结

综上,递归实现链表反转代码并不复杂,难度在于去理解这个递归调用的整个逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值