算法练习:单链表反转

单链表反转,是一道常见的面试题,题意和实现也并不复杂

如题:单链表 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就是下一层循环要更新的节点。