目录
1.迭代
2.递归
3.头插
重复某一过程,每一次处理结果作为下一次处理的初始值,这些初始值类似于状态,每次处理都会改变状态,直至到达最终状态
从前往后遍历连表,将当前节点的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
以相似的方法重复,类似于树结构,先从根节点找到叶子节点,从叶子节点开始便利大的问题(整个链表反转)拆成性质相同的小问题(两个元素反转)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);
}
先定义一个节点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;
根据多方资料学习 总结的笔记 如有侵权请联系。