码迷,mamicode.com
首页 > 其他好文 > 详细

数据结构-双向链表

时间:2015-05-19 07:35:16      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:

为了解决对链表操作的灵活性,把单链表的单一指向改为双向驱动,从而形成双向链表。JavaLinkedList就是双向链表的实现,但是因为有双端队列的成分,显得有些不单纯。

 

双向链表的节点定义

 

    private static class Node<E> {

        E item;

        Node<E> next;

        Node<E> prev;

 

        Node(Node<E> prev, E element, Node<E> next) {

            this.item = element;

            this.next = next;

            this.prev = prev;

        }

    }

 

这一节点定义的变化提高了对链表操作的性能,下面举一个例子:

 

    /**

     * Inserts element e before non-null Node succ.

     */

    void linkBefore(E e, Node<E> succ) {

        // assert succ != null;

        final Node<E> pred = succ.prev;

        final Node<E> newNode = new Node<>(pred, e, succ);

        succ.prev = newNode;

        if (pred == null)

            first = newNode;

        else

            pred.next = newNode;

        size++;

        modCount++;

    }

 

因为相邻前节点的信息已经被存储,可以直接通过这一信息获得前一个数据元素,而不是像单链表那样每次都从头再来。虽然花费了内存,但是提高了性能,从而节约了时间。有时候内存和性能是个平衡点的问题。

 

在这里,就不整篇幅的列举代码了,以下亮点特别说明一下。

二分查找的应用:

 

    /**

     * Returns the (non-null) Node at the specified element index.

     */

    Node<E> node(int index) {

        // assert isElementIndex(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;

        }

    }

接近前端从前开始,接近后端从后开始,比单链表显得“工业化”了些。

 

1.8版增加了spliterator处理,在将来spliterator会有很广泛的应用的。

 

    /**

     * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>

     * and <em>fail-fast</em> {@link Spliterator} over the elements in this

     * list.

     *

     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED} and

     * {@link Spliterator#ORDERED}.  Overriding implementations should document

     * the reporting of additional characteristic values.

     *

     * @implNote

     * The {@code Spliterator} additionally reports {@link Spliterator#SUBSIZED}

     * and implements {@code trySplit} to permit limited parallelism..

     *

     * @return a {@code Spliterator} over the elements in this list

     * @since 1.8

     */

    @Override

    public Spliterator<E> spliterator() {

        return new LLSpliterator<E>(this, -1, 0);

    }

 

    /** A customized variant of Spliterators.IteratorSpliterator */

    static final class LLSpliterator<E> implements Spliterator<E> {

        static final int BATCH_UNIT = 1 << 10;  // batch array size increment

        static final int MAX_BATCH = 1 << 25;  // max batch array size;

        final LinkedList<E> list; // null OK unless traversed

        Node<E> current;      // current node; null until initialized

        int est;              // size estimate; -1 until first needed

        int expectedModCount; // initialized when est set

        int batch;            // batch size for splits

 

        LLSpliterator(LinkedList<E> list, int est, int expectedModCount) {

            this.list = list;

            this.est = est;

            this.expectedModCount = expectedModCount;

        }

 

        final int getEst() {

            int s; // force initialization

            final LinkedList<E> lst;

            if ((s = est) < 0) {

                if ((lst = list) == null)

                    s = est = 0;

                else {

                    expectedModCount = lst.modCount;

                    current = lst.first;

                    s = est = lst.size;

                }

            }

            return s;

        }

 

        public long estimateSize() { return (long) getEst(); }

 

        public Spliterator<E> trySplit() {

            Node<E> p;

            int s = getEst();

            if (s > 1 && (p = current) != null) {

                int n = batch + BATCH_UNIT;

                if (n > s)

                    n = s;

                if (n > MAX_BATCH)

                    n = MAX_BATCH;

                Object[] a = new Object[n];

                int j = 0;

                do { a[j++] = p.item; } while ((p = p.next) != null && j < n);

                current = p;

                batch = j;

                est = s - j;

                return Spliterators.spliterator(a, 0, j, Spliterator.ORDERED);

            }

            return null;

        }

 

        public void forEachRemaining(Consumer<? super E> action) {

            Node<E> p; int n;

            if (action == null) throw new NullPointerException();

            if ((n = getEst()) > 0 && (p = current) != null) {

                current = null;

                est = 0;

                do {

                    E e = p.item;

                    p = p.next;

                    action.accept(e);

                } while (p != null && --n > 0);

            }

            if (list.modCount != expectedModCount)

                throw new ConcurrentModificationException();

        }

 

        public boolean tryAdvance(Consumer<? super E> action) {

            Node<E> p;

            if (action == null) throw new NullPointerException();

            if (getEst() > 0 && (p = current) != null) {

                --est;

                E e = p.item;

                current = p.next;

                action.accept(e);

                if (list.modCount != expectedModCount)

                    throw new ConcurrentModificationException();

                return true;

            }

            return false;

        }

 

        public int characteristics() {

            return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;

        }

    }

 

ArrayListLinkedList的区别

ArrayList

实现了List接口

数据元素在内部用数组保存

指定索引的get/set速度很快

插入和删除数据元素在某些场合要花点时间

 

LinkedList

除了List接口外,还实现了双端队列,是双向链表

虽然指定索引的get/set不太灵光,但插入和删除数据元素要比ArrayList表现的要好些。


数据结构-双向链表

标签:

原文地址:http://my.oschina.net/u/660460/blog/416509

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!