链表反转

一、要求

给定一个链表,要求把链表反转,假如原链表存储的值依次为 1->2->3->4->null;,
则要求输出结构为4 -> 3 -> 2 -> 1 -> null

二、分析

该链表的实现主要是要改变链表的指向。因此我们可以把问题分解成小模块,先不要想着如何把整个链表反转,而是先实现把两个结点反转,然后再依次循环实现整个链表的反转。这种把大问题化为小问题的思想正是递归思想,一般可以用递归实现的也就可以用迭代实现。接下来看一下如何用递归和迭代实现链表的反转?

三、代码实现

3.1递归实现
3.1.1思路
  1. 递归就是方法不断调用自身,直到条件结束。
  2. 这里结束条件是最后一个结点的链域等于NULL;
3.1.2代码
public LinkNode reversal(LinkNode head) {
        if (head == null || head.getNext() == null) {
            return head;
        }

        LinkNode next = head.getNext();
        LinkNode node = reversal(next); //不断的调用方法本身
        next.setNext(head);
        head.setNext(null);

        return  node;
    }

想要把递归这块的内部过程了解,我们需要借助堆栈的入栈和出栈来跟踪代码;
调用方法本身是在入栈,方法的返回是在出栈。

假设给定一个链表:
在这里插入图片描述
做入栈操作:入栈时用到的变量有head, next两个变量,我们来看看在入栈过程中两个变量的值变化
在插入图片描述
刚开始传递的时整个链表head,只要链表还有结点,就让next指向下一个结点再把该结点作为参数传进去,直到为最后一个结点时,返回,这是就到了出栈的过程:
做出栈操作:出栈时用到的变量有head, next,node三个变量,我们来看看在出栈过程中三个变量的值变化
在这里插入图片描述
刚开始栈顶弹出的是链表的最后一个结点,每次出栈都让后一个结点指向前一个结点,再把前一个结点的链域设置为NULL,当全部出栈,把保存了最后结果的node值返回。

总结:使用递归虽然代码简洁,但是不好理解,而且递归调用方法,浪费空间,而且如果链表太长还容易造成堆栈的溢出。
3.2迭代实现
3.2.1思路
  1. 利用变量的原值推算出变量的一个新值,迭代就是A不停的调用B。
  2. 这里我们需要定义三个变量:
  3. 一个表示当前节点,该节点可以用来当作循环条件;
  4. 一个表示直接前驱节点,初始化为null,就可以巧妙的把反转后的链表的最后一个结点的链域设置成null;因为是从链表的第一个结点开始遍历链表,所以第一个结点也就是反转后的最后一个结点,如果刚开始不给它的链域设置null,后面就没有机会了;
  5. 一个表示直接后继结点,当前面的改变指向后,这个变量可以用来保存剩余结点;
  6. 最后用遍历来不断改变这三个变量的值;就可实现反转;
3.2.2代码
public LinkNode reversal(LinkNode node) {
        LinkNode pro = null; //直接前驱节点
        LinkNode curr = node; //当前结点
        LinkNode next = null; //直接后继节点
        while(curr != null) {
            next = curr.getNext();
            curr.setNext(pro);
            pro = curr;
            curr = next;
        }
        return pro;
    }

先把代码思路过一遍:
在这里插入图片描述

  1. 刚开始传进来一个node链表,先让curr指向该链表;
  2. 然后开始遍历,让next指向下一个结点,curr指向pro,因为pro初始化为null,所以这时候就把第一个结点的链域设置成null了;
  3. 然后让pro指向当前结点curr,curr指向next;
  4. next再后移一个结点;
总结:这里一定要注意顺序,顺序不对会导致值被覆盖,不能达到目的。

优点:使用迭代效率高,运行时间只因循环次数增加而增加;而且没什么额外开销,空间上也没有什么增加

缺点: 不容易理解;代码不如递归简洁; 编写复杂问题时困难。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值