Java常用数据结构LinkedList

之前已经总结了 Set, List, Map 的结构,从本文开始就介绍具体的类,本文就介绍一下 LinkedList

640?wx_fmt=pngLinkedList 是双向链表,如上图所示,为 LinkedList 的继承实现结构。主要说下 Deque 接口, Deque 接口主要提供了对现行集合从头部和尾部对元素进行添加,删除和访问的能力。可以看下 Deque 接口定义的方法:

640?wx_fmt=png

由于 LinkedList 实现了以上接口,故可以灵活对 LinkedList 从头部和尾部进行元素相关的操作。

存储单元

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

以上为 LinkedList 的节点类。 LinkedList 的每一个节点都存储了自己的前向和后继节点的指针。为了从头或者尾快速访问链表中的节点, LinkedList 存储了链表的头结点 first 和尾节点 last ,并用 size 记录链表的节点数量。

添加

初始化时,构建一个空的 LinkedList,然后添加一个元素。

add(E)	
add(int ,E)	
addLast(E)	
addAll(Collection<? extends E>)	
addAll(int index, Collection<? extends E> c)	
addFirst(E)

LinkedList 提供的这 6 种添加元素的方法,除了最后一种时在链表头插入之外,其他的都是在链表的尾节点插入。添加节点时,如果指定了添加节点的位置,比如 add(int,E),则需要寻找指定位置的节点。可以看下相应的逻辑:

public void add(int index, E element) {	
    checkPositionIndex(index);	
    if (index == size)	
        linkLast(element);	
    else	
        linkBefore(element, node(index));	
}

首先判断插入点是否在 size 的范围之内,然后判断插入点是否在最后一个节点之后,如果是则直接插入到最后,否则会执行 node(index) 函数,找到 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;	
    }	
}

node 函数在查找 index 位置的元素时并没有直接从头查找,而是将链表从中间分为前后两段,如果 ndex 位置小于链表长度的 1/2 ,则直接从头开始向后查找;如果 index 大于链表长度的 1/2 ,则从链表尾部开始向前查找。

删除

remove()	
remove(int)	
remove(Object)	
removeFirst()	
removeLast()	
removeFirstOccurrence(Object)	
removeLastOccurrence(Object)

以上为 LinkedList 提供的所有的删除函数。 

remove(), removeFirst() 删除头节点;

removeLast() 删除尾节点; 

removeFirstOccurrence 从头结点开始遍历,删除第一次出现的目标节点; 

removeLastOccurrence 从尾节点开始遍历,删除第一次出现的目标节点。

清除

清除操作是执行的是 clear() 函数。

public void clear() {	
    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++;	
}

clear() 函数从头结点开始遍历,将每一个节点的值 item 以及前向节点和后继节点全部置空,便于进行gc。

总结

  • LinkedList 是双向链表,可以从头部和尾部对元素进行访问,添加和删除,可以将其看作是栈或者队列

  • LinkedList 的节点只保存了插入值和前向以及后继节点

  • 在根据位置index对元素进行访问时, LinkedList 会将链表长度除以 2,如果 index 在链表的前半部分,则从头部向后开始遍历,如果 index 在后半部分,则从尾部开始向前遍历

  • 对链表执行 clear 操作时, LinkedList 会将每一个节点的前向和后继节点的指针置空,便于gc

--END--

识别二维码,关注我们

640?wx_fmt=png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值