単独リンクリストの反転(ジャワ)

序文

:単独リンクリストの反転がleetcode(電源ボタン)206タイトルがある206のリンクリストを逆に
すべての最初の単独リストをリンクされているものを知っている必要があり、単独でリンクリストを反転させるために。前のグラフィックデータ構造:配列と一本鎖は、非常に単独リストをリンクされているものの分析を詳述されています。

単独リンクリスト構造

/**
 * 单链表
 */
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;
}

逆転させるための3つのポインタ

前の3つのポインタ、それぞれ、CURRは、次の3つの連続したノードを指し、ノードはCURR表すノードの後続ノードを変更する必要性を、すなわち:CURR後継ノードはそれぞれ、前のノードを指すように変更今、次のノードを指すようになりますこの操作を行った後(最初のノード以外)のノードは、リンクされたリストが逆になります。全体のプロセス図は次のとおりです。
ここに画像を挿入説明
図、実装コードを見てのプロセスを理解するために、それは明らかです。

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;
}

リカーシブ

ヘッドノードに加えて、リスト全体を反転する反転に等しく、後続ポインタの残りの部分は、反転点の後にリストを連結し、ヘッドノードを返します。これは、より小さなサブ問題に当初発行することができますので、再帰的なアルゴリズムを記述します。書き込みへの再帰アルゴリズム以下のコードが、しかし、ではない3つのポインタより直感的な方法として。ここでは、再帰的な方法は次のとおりです。

/**
 * 反转链表(递归版)
 *
 * @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;
}

検証

2つの反転方式の正当性を検証するために、この方法は、最初に、焦点ではないので、それは直接与え、リストに単一の追加要素を記述しなければなりません。単一リンクリストを印刷する、単一リンクリスト、単一の反転リストに要素を追加して、単一の連結リスト構造定義:ここで完全なソースコードであって、です。

/**
 * 单链表
 */
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();
    }
}

試験方法

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);
}

結果:

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

概要

シングルは逆線形データ構造がノードを検索するだけで、現在のノードの後、主に単一のリストに基づいて、難しいことではありませんので、どこにでも限ら操作感。これは、いくつかの補助ポインタの完全な反転操作で、発散思考する必要があります。
もちろん、二つの方法上記に加えて、いくつかの簡単な、粗方法がある:長さの配列として直接オープンシングルノードリストの数に等しい、リストのノードが単一の配列に、次いで、逆の順序トラバーサルの配列は、単一のリンクリストに再構成される。またはでスタック(スタック)LIFOの特性等。アルゴリズムは比較的簡単です、詳細には触れません。

公開された52元の記事 ウォンの賞賛107 ・は 10000 +を見て

おすすめ

転載: blog.csdn.net/Baisitao_/article/details/102964765