阅读 42
LinkList是基于链表实现的 那是怎么实现的?(入门)

LinkList是基于链表实现的 那是怎么实现的?(入门)

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

1.回顾

在上一篇文章中,我主要分享了ArrayList的一些内容,主要是ArrayList他是基于数组实现的, 但是Linklist他底层是基于链表实现的 今天我只要想分享一下Linklist他的插入时如何实现的

2.LinkList

image.png

我们可以看见 他定义了一个头结点和一个尾结点(头指向第一个节点 尾指向最后一个节点) 那对于Node类型:


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;
    }
}
复制代码

其中 next是他指向后继的结点,prev是指向前驱的结点 正式他有这两个“指针”他在删除和插入的过程中不需要向前向后移动元素 而是修改指针的指向即可。

  • 插入 将指定集合中的所有元素插入此列表
public boolean addAll(int index, Collection<? extends E> c) {
    checkPositionIndex(index);

    Object[] a = c.toArray();
    int numNew = a.length;
    if (numNew == 0)
        return false;

    Node<E> pred, succ;
    if (index == size) {
        succ = null;
        pred = last;  //pred 前驱节点
    } else {
        succ = node(index);
        pred = succ.prev;
    }

    for (Object o : a) {
        @SuppressWarnings("unchecked") E e = (E) o;
        Node<E> newNode = new Node<>(pred, e, null);
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        pred = newNode;
    }

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

    size += numNew;
    modCount++;
    return true;
}
复制代码

从这上面这一段代码(我结合自己对链表的一些知识) 基于一些数据结构的知识,我们看这段代码

  1. 其中我们根据需要插入的数据来找到插入数据的前驱节点即pred 而其中succ节点应该就是我们数据插入的数据节点
  2. 我们又对传入的数据进行遍历(创建新节点new Node<>(pred, e, null);)插入节点(若newNode是第一个节点就将first节点指向这个节点,若不是 则前驱节点指向的下一个节点就是这个节点) 最后修改前驱节点(往下移)

在这里就可以举个例子来加深对链表的理解 一群小朋友牵手玩游戏(左右手就相当于链表的前驱后继节点) 一个小朋友发现自己是第一个则自己就当第一个节点,第二个小朋友加入进来,则第一个小朋友就要用自己的右手牵其第二个小朋友的手依次类推下去,突然一个小朋友中途加入第二和第三个小朋友中间,这时第二第三个小朋友就需要断开他们之间牵手 分别都要去牵起刚加入的小朋友,过一会第三个小朋友想要离队 则第二和第四小朋友重新牵手又可以愉快的玩耍了。

3.总结

其实只要知道链表的操作和思想,去看了源码发现都差不多 这也提示我每一个方法 每一个类 他实现背后的逻辑是什么 是我有时需要去关注的 只要理解这个思想 不管用什么语言 都可以理解

文章分类
后端
文章标签