数据结构-双向链表

在这里插入图片描述

一. 双向链表的特点

  • 每个节点维护了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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章