Singly linked list reversal (Java)

Foreword

Singly linked list reversal is leetcode (power button) 206 title: 206. reverse a linked list
in order to reverse a singly linked list, first of all have to know what is singly linked list. The previous graphical data structures: arrays and single-chain has been very detailed analysis of what is singly linked list.

Singly linked list structure

/**
 * 单链表
 */
public class SingleLinkedList<E> {

    /**
     * 内部节点
     */
    private class Node {
        private E e;
        private Node next;

        public Node(E e, Node next) {
            this.e = e;
            this.next = next;
        }

        public Node(E e) {
            this(e, null);
        }
    }

	// 头节点
    private Node head;
    // 节点个数
    private int size;
}

Three pointers for reversing

Prev three pointers, respectively, Curr, pointing next three consecutive nodes, the nodes represent Curr need to modify the node's successor nodes , i.e.: curr successor node would point to next node, now changed to point to prev nodes, each node (except the first node) after performing this operation, the linked list is reversed. The whole process diagram is as follows:
Here Insert Picture Description
to understand the process of FIG, look at the implementation code, it should be clear.

public Node reverse() {
    if (head == null || head.next == null) {
        // 空链表和只有一个节点的链表,反转后还是原来的结构
        return head;
    }
    Node prev = head;
    Node curr = prev.next;
    Node next = null;
    while (curr != null) {
        next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;
    }
    head.next = null;
    head = prev;
    return head;
}

Recursive

Inverting the entire list, in addition to the head node is equal to inversion, the rest of the subsequent pointer linked list after the reversal point and return the head node. This allows the original issue into smaller sub-problems, so write recursive algorithm. Although recursive algorithm less code to write, but not as a method more intuitive three pointers. Here is the recursive method:

/**
 * 反转链表(递归版)
 *
 * @return
 */
public Node reverse() {
    if (head == null) {
        return null;
    }
    reverse(head);
    return head;
}

/**
 * 反转以node为头结点的单链表,并且返回反转后的尾结点(反转之后就成了尾结点)
 *
 * @param node
 * @return
 */
private Node reverse(Node node) {
    if (node.next == null) {
        head = node;
        return node;
    }
    Node lastTail = reverse(node.next);
    node.next = null;
    lastTail.next = node;
    return node;
}

verification

In order to verify the correctness of the two inversion method, the method must first write a single add elements to the list, because it is not the focus, it gives directly. Here is the complete source code, comprising: a single linked list structure definition, adding elements to a single linked list, a single inverted list, print a single linked list.

/**
 * 单链表
 */
public class SingleLinkedList<E> {

    /**
     * 内部节点
     */
    private class Node {
        private E e;
        private Node next;

        public Node(E e, Node next) {
            this.e = e;
            this.next = next;
        }

        public Node(E e) {
            this(e, null);
        }
    }

    private Node head;
    private int size;

    /**
     * 链表尾部新增节点
     *
     * @param e
     */
    public void add(E e) {
        head = add(head, e);
    }

    /**
     * 向以node为根节点的链表插入节点,并返回插入后的链表
     *
     * @param node
     * @param e
     * @return
     */
    private Node add(Node node, E e) {
        if (node == null) {
            // 递归结束条件
            size++;
            return new Node(e);
        }
        node.next = add(node.next, e);
        return node;
    }

    /**
     * 反转链表(非递归版)
     * @return
     */
//    public Node reverse() {
//        if (head == null || head.next == null) {
//            // 空链表和只有一个节点的链表,反转后还是原来的结构
//            return head;
//        }
//        Node prev = head;
//        Node curr = prev.next;
//        Node next = null;
//        while (curr != null) {
//            next = curr.next;
//            curr.next = prev;
//            prev = curr;
//            curr = next;
//        }
//        head.next = null;
//        head = prev;
//        return head;
//    }

    /**
     * 反转链表(递归版)
     *
     * @return
     */
    public Node reverse() {
        if (head == null) {
            return null;
        }
        reverse(head);
        return head;
    }

    /**
     * 反转以node为头结点的单链表,并且返回反转后的尾结点(反转之后就成了尾结点)
     *
     * @param node
     * @return
     */
    private Node reverse(Node node) {
        if (node.next == null) {
            head = node;
            return node;
        }
        Node lastTail = reverse(node.next);
        node.next = null;
        lastTail.next = node;
        return node;
    }

    /**
     * 输出链表信息
     *
     * @return
     */
    @Override
    public String toString() {
        StringBuilder result = new StringBuilder();
        Node curr = head;
        while (curr != null) {
            result.append(curr.e).append("->");
            curr = curr.next;
        }
        result.append("NULL");
        return result.toString();
    }
}

Test Methods

public static void main(String[] args) {
    SingleLinkedList<Integer> list = new SingleLinkedList();
    for (int i = 0; i < 7; i++) {
        list.add(i);
    }
    System.out.println(list);
    list.reverse();
    System.out.println(list);
}

Results of the:

反转前:0->1->2->3->4->5->6->NULL
反转后:6->5->4->3->2->1->0->NULL

to sum up

Single is a reverse linear data structure is not difficult, mainly based on a single list only after the current node to find a node, so the operation feeling everywhere limited. It is necessary to divergent thinking, with some auxiliary pointers complete inversion operation.
Of course, in addition to the above two methods, there are some simple and crude method: direct open as an array of length equal to the number of single-node list, the list node into a single array, then the array in reverse order traversal, reconfigured to a single linked list. Or with a stack (Stack) the LIFO properties and the like. Algorithm is relatively simple, not go into details.

Published 52 original articles · won praise 107 · views 10000 +

Guess you like

Origin blog.csdn.net/Baisitao_/article/details/102964765