LinkedList

LinkedList

Doubly-linked list implementation of the List and Deque interfaces. Implements all optional list operations, and permits all elements (including null).

双链表实现了list和Deque接口。实现所有可选的列表操作,并允许所有元素(包括null)。

All of the operations perform as could be expected for a doubly-linked list. Operations that index into the list will traverse the list from the beginning or the end, whichever is closer to the specified index.

所有的操作都可以像预期的那样执行一个双链表。索引到列表中的操作将从开始或结束遍历列表,以最接近指定索引的那一个为准。

Note that this implementation is not synchronized. If multiple threads access a linked list concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements; merely setting the value of an element is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the list. If no such object exists, the list should be “wrapped” using the Collections.synchronizedList method. This is best done at creation time, to prevent accidental unsynchronized access to the list:
List list = Collections.synchronizedList(new LinkedList(…));

该线程不是线程安全的。

The iterators returned by this class’s iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the Iterator’s own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

linkedList是由双向链表组成的,如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zv95P8wL-1615737760012)(C:\Users\10374\AppData\Roaming\Typora\typora-user-images\image-20210314223945658.png)]

出了第一个节点和最后一个节点外,中间的节点每一个都有前驱和后继节点。

参数

transient int size = 0;

//指向头结点
transient Node<E> first;

//指向尾结点的
transient Node<E> last;

构造函数

//空参构造函数
public LinkedList() {
}

//构造一个包含指定元素的列表集合,按照集合返回的顺序迭代器。
public LinkedList(Collection<? extends E> c) {
    this();
    addAll(c);
}

加入一个头节点

/**
 * Links e as first element.
 */
private void linkFirst(E e) {
    final Node<E> f = first;
    final Node<E> newNode = new Node<>(null, e, f);
    first = newNode;
    if (f == null)
        last = newNode;
    else
        f.prev = newNode;
    size++;
    modCount++;
}
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;
        }
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-76PYfayo-1615737760023)(C:\Users\10374\AppData\Roaming\Typora\typora-user-images\image-20210314233233252.png)]

加入一个值为5的节点。

加入一个尾结点与之类似,将尾结点作为新节点的前驱,然后将新尾结点作为原尾结点的后继。

非空节点前插入节点

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ArKRvCnw-1615737760024)(C:\Users\10374\AppData\Roaming\Typora\typora-user-images\image-20210314234108855.png)]

在3前插入5。

add方法

/**
 * Inserts the specified element at the specified position in this list.
 * Shifts the element currently at that position (if any) and any
 * subsequent elements to the right (adds one to their indices).
 *
 * @param index index at which the specified element is to be inserted
 * @param element element to be inserted
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public void add(int index, E element) {
    checkPositionIndex(index);

    if (index == size)
        linkLast(element);
    else
        linkBefore(element, node(index));
}
    /**
     * 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;
        }
    }

add方法先通过方法找到要插入节点的位置,然后通过linkBefore方法进行插入。

remove方法

//从列表中删除第一个出现的指定元素,如果它存在。如果该列表不包含元素,则包含元素不变。更正式的做法是删除索引最低的元素
public boolean remove(Object o) {
    if (o == null) {
        for (Node<E> x = first; x != null; x = x.next) {
            if (x.item == null) {
                unlink(x);
                return true;
            }
        }
    } else {
        for (Node<E> x = first; x != null; x = x.next) {
            if (o.equals(x.item)) {
                unlink(x);
                return true;
            }
        }
    }
    return false;
}
    E unlink(Node<E> x) {
        // assert x != null;
        final E element = x.item;
        final Node<E> next = x.next;
        final Node<E> prev = x.prev;

        if (prev == null) {
            first = next;
        } else {
            prev.next = next;
            x.prev = null;
        }

        if (next == null) {
            last = prev;
        } else {
            next.prev = prev;
            x.next = null;
        }

        x.item = null;
        size--;
        modCount++;
        return element;
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K4qgPW1P-1615737760027)(C:\Users\10374\AppData\Roaming\Typora\typora-user-images\image-20210314235455723.png)]

remove方法先找到要删除的值的位置,然后通过unlink方法进行删除。

set方法

public E set(int index, E element) {
    checkElementIndex(index);
    Node<E> x = node(index);
    E oldVal = x.item;
    x.item = element;
    return oldVal;
}

找到要set的值,返回 原始值

get方法

public E get(int index) {
    checkElementIndex(index);
    return node(index).item;
}

总结

linkedlist底层是有首尾指针的双向链表,头插和尾插都有很好的效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值