數據結構-雙向鏈表

在這裏插入圖片描述

一. 雙向鏈表的特點

  • 每個節點維護了prev,next 兩個節點和 元素e
  • 不僅可以像單鏈表向後查找,還可以向前查找。
  • 添加/刪除第一個節點和最後一個節點一個節點的時間複雜度都是O(1)
  • 查找的時候,可以判斷index 在前半部分還是後半部分,查找節點。

二.雙向鏈表的插入和刪除

插入節點:首先找到要插入節點newNode的位置,並且找到前一個節點prevNode,和後一個節點nextNode, prevNode的next 指向新的節點,newNode的prev 指prevNode,newNode節點next指向nextNode,nextNode的prev指向newNode 示意圖如下:

在這裏插入圖片描述

刪除節點:找到刪除delNode的節點的位置,並且找到前一個節點prevNode,和後一個節點nextNode, prevNode的next 指向nextNode,newNode的prev 指prevNode ,如下圖:
在這裏插入圖片描述

三. 雙向鏈表時間複雜度分析

  • 刪除/新增 第一個和最後一個元素的時間複雜度爲O(1)
  • 刪除/新增 元素的時間複雜度爲O(n)

四.Java 雙向鏈表的簡單實現

/**
 * @author 一直往前走
 * @date 2019/08/02
 */
public class DoubleList<E> {

    public Node<E> first;
    public Node<E> last;

    public int size;
    public int modCount;

    public DoubleList() {

    }

    /**
     * 添加第一個元素
     *
     * @param e
     */
    public void addFirst(E e) {
        final Node f = first;
        final Node newNode = new Node<E>(null, e, f);
        if (f == null) {
            last = newNode;//newNode賦值last
        } else {
            first.prev = newNode; //newNode賦值給first.prev
        }
        newNode.next = first;
        first = newNode;
        size++;
        modCount++;
    }

    /**
     * 添加最後一個元素
     *
     * @param e
     */
    public void addLast(E e) {
        final Node l = last;
        final Node newNode = new Node(l, e, null);
        if (l == null) {
            first = newNode;
        } else {
            last.next = newNode;
        }
        newNode.prev = last;
        last = newNode;
        size++;
        modCount++;
    }

    public void add(int index, E e) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("Add failed. index illegal");
        }
        if (index == 0) {
            addFirst(e);
        } else if (index == size) {
            addLast(e);
        } else {
            addBefore(e, node(index));
        }
    }

    /**
     * 根據index位置獲取節點
     * 利用雙向鏈表的特點提高查找效率
     *
     * @param index
     * @return
     */
    private Node<E> node(int index) {
        if (index < (size >> 1)) {  //說明要查找的節點在前半部分
            Node<E> x = first;
            for (int i = 0; i < index; i++) {
                x = x.next;
            }
            return x;
        } else {  //說明要查找的節點在前半部分
            Node<E> x = last;
            for (int i = size - 1; i > index; i--) {
                x = x.prev;
            }
            return x;
        }
    }

    /**
     * 在節點node前添加元素e
     *
     * @param e
     * @param node
     */
    public void addBefore(E e, Node node) {
        Node prev = node.prev;
        Node newNode = new Node(prev, e, node);
        if (prev == null) {
            first = newNode;
        } else {
            prev.next = newNode;
        }
        node.prev = newNode;
        size++;
        modCount++;
    }

    /**
     * 在節點node後添加元素e
     *
     * @param e
     * @param node
     */
    public void addAfter(E e, Node node) {
        Node next = node.next;
        Node newNode = new Node(node, e, next);
        if (next == null) {
            last = newNode;
        } else {
            next.prev = newNode;
        }
        node.next = newNode;
        size++;
        modCount++;
    }

    /**
     * 雙鏈表
     *
     * @param <E>
     */
    class Node<E> {
        public E e;
        public Node next, prev;

        public Node() {
            e = null;
            next = null;
            prev = null;
        }

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

        public String toString() {
            StringBuilder sb = new StringBuilder();
            Node cur = this;
            while (cur != null) {
                sb.append(cur.e + "->");
                cur = cur.next;
            }
            sb.append("NULL");
            return sb.toString();
        }

    }

    public static void main(String[] args) {
        DoubleList<Integer> doubleList = new DoubleList();
        for (int i = 0; i < 10; i++) {
            doubleList.addFirst(i);
            System.out.println(doubleList);
        }
        doubleList.add(1, 2);
        System.out.println(doubleList);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章