链表反转~

目录

1.迭代

 2.递归

3.头插


1.迭代

重复某一过程,每一次处理结果作为下一次处理的初始值,这些初始值类似于状态,每次处理都会改变状态,直至到达最终状态

从前往后遍历连表,将当前节点的next指向上一个节点,因此需要一个变量存储上一个节点prev,当前节点处理完需要寻找一下个节点,因此需要一个变量保存当前节点curr,处理完后要将当前节点赋值给prev,并将next指针赋值给curr,因此需要一个变量提前保存一下个节点的指针next

// 内部类
static class ListNode {
    int val; // 当前值
    ListNode next;  // 指向的下一个节点

    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}
----------------------------------------------------

反转前:
ListNode node5 = new ListNode(5, null);
ListNode node4 = new ListNode(4, node5);
ListNode node3 = new ListNode(3, node4);
ListNode node2 = new ListNode(2, node3);
ListNode node1 = new ListNode(1, node2);
// 目前指针指向情况: 1->2->3->4->5->null
System.out.println("node1 = " + node1);

----------------------------------------------------

// 使用迭代方法
public static ListNode iterate(ListNode head) {

    ListNode prev = null, next;
    ListNode curr = head; // 当前节点
    while (null!=curr) {
        // 先将下一个指针保存
        next = curr.next;
        curr.next = prev; //prev 指向的是上一个节点,这里是关键 反转
        // 结束赋值后可以迭代下一个节点,迭代前先现将当前节点存储,下一个节点进来,这个节点就变成了前一个节点
        prev = curr;
        curr = next; // 此时第二个节点进入
    }
    return prev;
    // 循环走到最后 prev:{val:5,next:4} // 因为 curr.next = prev; 这步做了反转,变成了指向上一个节点,这就完成了我们的需求
}

----------------------------------------------------

反转后:
ListNode node5 = new ListNode(5, null);
ListNode node4 = new ListNode(4, node5);
ListNode node3 = new ListNode(3, node4);
ListNode node2 = new ListNode(2, node3);
ListNode node1 = new ListNode(1, node2);
// 目前指针指向情况: 1->2->3->4->5
ListNode prev = iterate(node1);
System.out.println("prev = " + prev);
// 反转后 5->4->3->2->1->null

 2.递归

以相似的方法重复,类似于树结构,先从根节点找到叶子节点,从叶子节点开始便利大的问题(整个链表反转)拆成性质相同的小问题(两个元素反转)curr.next.next=curr 将所有的小问题解决,大问题即解决

只需要每个元素都执行curr.next.next=curr,curr.next=null 两个步骤即可,为了保证链不断 必须从最后一个元素开始

// 递归
public static ListNode recursion(ListNode head) {
    // 找到最后一个节点
    if (head == null || head.next==null) {
        return head; // 返回倒数第二个节点
    }
    ListNode new_head= recursion(head.next); //递归拿到最后一个节点,new_head就是最后一个节点5, (倒数第二个节点4)
    head.next.next = head;// 分析值:head.next.next(4->5->null); head(4->5->null); 赋值后:(4->5->4->5...无线循环)
    head.next = null;// 断开4.next=5的关系 ,剩余关系 5.next=4; 断开3.next=4的指针,剩余 4.next=3 ...
    return new_head;
}

---------------------------------------------

public static void main(String[] args) {
    ListNode node5 = new ListNode(5, null);
    ListNode node4 = new ListNode(4, node5);
    ListNode node3 = new ListNode(3, node4);
    ListNode node2 = new ListNode(2, node3);
    ListNode node1 = new ListNode(1, node2);
    ListNode prev = recursion(node1);
    // 反转后 5->4->3->2->1->null
    System.out.println("prev = " + prev);
}

3.头插

 先定义一个节点reverseHead=new HeroNode();

从头到尾遍历原来的链表,每遍历一个节点,将其取出,并放在新的链表reverseHead的最前端

原来的链表的head.next=reverseHead.next

public static void reversal(HeroNode head) {
    // 当前链表只有一个或者为空就无须反转,直接返回
    if (head.next == null || head.next.next==null) {
        return;
    }
    // 定义一个辅助变量(指针),帮助我们遍历原来的链表
    HeroNode cur = head.next;// 我们原来的链表
    HeroNode next = null;// 指向当前节点的下一个节点
    HeroNode reverseHead = new HeroNode(0, "", "");
    //  遍历原来的链表
    // 并从头到尾遍历原来的链表,每遍历一个节点,就将其取出,并放在新链表reverseHead的最前端
    while (cur != null) {
        next = cur.next;// 先暂时保留当前节点的下一个节点
        cur.next = reverseHead.next;// 将cur的下一个节点指向新的链表的最前端
        reverseHead.next = cur;// 将cur链接到新的链表上
        cur = next;// 后移

    }
    // 将head.next指向 reverseHead.next 就完成单链表反转
    head.next = reverseHead.next;
}
---------------------------------------------------------------
psvm
// 创建节点
HeroNode heroNode1 = new HeroNode(1, "松江", "及时雨");
HeroNode heroNode2 = new HeroNode(2, "卢俊义", "玉麒麟");
HeroNode heroNode3 = new HeroNode(3, "吴用", "智多星");
HeroNode heroNode4 = new HeroNode(4, "林冲", "豹子头");

// 创建链表
SingleLinkedList singleLinkedList = new SingleLinkedList();

singleLinkedList.add(heroNode1);
singleLinkedList.add(heroNode2);
singleLinkedList.add(heroNode3);
singleLinkedList.add(heroNode4);
singleLinkedList.showLinked();

System.out.println("反转前:");
singleLinkedList.showLinked();
// 测试链表反转
System.out.println("反转后:");
reversal(singleLinkedList.getHead());
singleLinkedList.showLinked();

详细分析:

例如:链表 1>2>3
  next = cur.next;// 先暂时保留当前节点的下一个节点
  cur.next = reverseHead.next;// 将cur的下一个节点指向新的链表的最前端
  reverseHead.next = cur;// 将cur链接到新的链表上
  cur = next;// 后移
  
 第一次进入循环
next=2;
cur.next=null;
reversHead.next=1;
cur=2;
此时链表情况: reverseHead.next= 1
第二次进入循环
next=3;
cur.next=1;
reversHead.next=2;
cur=3;
此时链表情况: reverseHead.next= 2>1
第三次进入循环
next=null;
cur.next=2;
reversHead.next=3;
cur=null;
此时链表情况: reverseHead.next= 3>2>1
reverseHead节点只是用来做反转的此时需要还给head
head.next = reverseHead.next;

 根据多方资料学习 总结的笔记  如有侵权请联系。

猜你喜欢

转载自blog.csdn.net/weixin_46522803/article/details/121565593