LinkedList源码笔记

链表结构

不同于数组与向量中各数据项的物理存放位置与逻辑次序完全对应,链表中的元素虽然也构成一个线性逻辑次序,但其元素的物理地址可以任意

链表中的元素维护一个前驱与后继,分别指向上一个元素与下一个元素的地址。

头尾节点与首末节点

链表结构中,除了可见的首末节点first、last,还有不可见的头尾节点header、trailer。

创建链表时即创建头尾节点,first时头节点的后继,last是尾节点的前驱。这种设计方法使得相关算法不必再对各种边界退化情况做专门处理。

Java中对链表的实现LinkedList

LinkedList中实现了一个内部私有类,其中next指向下一个节点,prev指向前一个节点,item是当前节点的值

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

另外还有两个内部私有变量size与modCount。

其中modCount用于记录LinkedList被修改的次数。

LinkedList提供两个构造方法

    public LinkedList() {
}

public LinkedList(Collection<? extends E> c) {
    this();
    addAll(c);
}

LinkedList添加元素

在首次创建LinkedList时调用add(E e)函数,last == first == null。

将新创建的节点前驱指向LinkedList的last,即指向头节点null。

新节点newNode(l,e,null),将l即最后一个节点作为前驱,此时指向null。null作为后继,即指向不可见的尾节点,值为e。

将LinkedLits的last 指向新创建的节点。

满足 l == null,将LinkedList的first指向该节点。

此时列表中只有一个节点和隐含的两个不可见的头尾节点。


在LinkedList已有元素时调用add(E e),last指向最后一个节点,first指向第一个节点。

l = last 指向最后一个节点。

新节点newNode(l,e,null),将l即最后一个节点作为前驱。null作为后继,即指向不可见的尾节点,值为e。

将LinkedList的last替换为新节点newNode。

l != null,不满足条件语句将l的后继替换成新节点newNode,不再指向null。

    public boolean add(E e) {
        linkLast(e);
        return true;
}

void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null)
        first = newNode;
    else
        l.next = newNode;
    size++;
    modCount++;
}

在指定的索引处添加元素

当index == size,将e作为最后一个节点链接。

当index != size,将新节点(值为e)插入index的位置。node(index)的前驱作为新节点的前驱,node(index)作为新节点的后继。

    public void add(int index, E element) {
        checkPositionIndex(index);//对index进行有效性判定

        if (index == size)
            linkLast(element);
        else
            linkBefore(element, node(index));
    }
    /**
     * Links e as last element.
     */
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }
    /**
     * 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;
        }
    }

删除节点,默认删除首节点。

    public E remove() {
        return removeFirst();
    }
    public E removeFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }
    private E unlinkFirst(Node<E> f) {
        // assert f == first && f != null;
        final E element = f.item;
        final Node<E> next = f.next;
        f.item = null;
        f.next = null; // help GC
        first = next;
        if (next == null)
            last = null;
        else
            next.prev = null;
        size--;
        modCount++;
        return element;
    }

清除整个节点

    public void clear() {
        // Clearing all of the links between nodes is "unnecessary", but:
        // - helps a generational GC if the discarded nodes inhabit
        //   more than one generation
        // - is sure to free memory even if there is a reachable Iterator
        for (Node<E> x = first; x != null; ) {
            Node<E> next = x.next;
            x.item = null;
            x.next = null;
            x.prev = null;
            x = next;
        }
        first = last = null;
        size = 0;
        modCount++;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值