单链表反转,是一道常见的面试题,题意和实现也并不复杂
如题:单链表 e1>e2>e3>e4>e5
反转后:e5>e4>e3>e2>e1 经过反转后,所有指向都是反过来的
上代码:
package com.example.demo.test;
class Element {
String name;
Element next;
public Element(String name) {
this.name = name;
}
public void setNext(Element next) {
this.next = next;
}
}
public class ReverseLinkedList {
public static void main(String[] args) {
Element e1 = new Element("e1");
Element e2 = new Element("e2");
Element e3 = new Element("e3");
e1.setNext(e2);
e2.setNext(e3);
System.out.println("----反转前----");
Element self = e1;
while(self.next != null) {
System.out.println(self.name + "的next:" +self.next.name);
self = self.next;
}
reverseList(e1);
System.out.println("----反转后----");
Element self2 = e3;
while(self2.next != null) {
System.out.println(self2.name + "的next:" +self2.next.name);
self2 = self2.next;
}
}
public static void reverseList(Element head) {
Element self = head;
Element prev = null;
while(self != null) {
//这里只关注当前节点的前一个节点
//而不需要在这里即设置当前节点的前一节点,也设置当前节点的下一节点的指向,
//如果这样设置了,代码进入死循环,例如: self.next.next = self
//而是在每一次循环中处理当前节点的前一节点
Element next = self.next;//取出当前节点的next节点
self.next = prev;//反转指针,当前节点的next节点指向前一节点
prev = self;//更新前一节点指针,下次循环使用
self = next;//当当前节点指向下一节点,准备接入下一次循环,来处理第二个节点的反转
}
}
}
输出结果:
----反转前----
e1的next:e2
e2的next:e3
----反转后----
e3的next:e2
e2的next:e1
技巧总结:
我们在每层循环中只关注当前节点的next节点的指向,这里要做反转,就是更新当前节点的next节点指向其前驱节点,所以使用了一个prev变量来保存每次循环要使用的前驱节点。在每层循环最后prev = self,都把当前节点设置为前驱节点,为了下一层循环做准备,self = next就是下一层循环要更新的节点。