关于Java:在ArrayList 与LinkedList 中间插入

Insertion in the middle of ArrayList vs LinkedList

本问题已经有最佳答案,请猛点这里访问。

在Java的上下文中交谈。如果我想插入一个ArrayList或一个linkedList的中间,我被告知ArrayList会表现得很糟糕。

我理解这是因为,我们需要移动所有元素,然后进行插入。这应该是N/2的顺序,即O(N)。

但对于linkedList来说,情况不同吗?对于链表,我们需要遍历到找到中间位置,然后进行指针操作。在这种情况下,也需要O(N)时间。不是吗?

谢谢


这里的原因是链接列表中的元素没有实际的移动。链接列表是由节点组成的,每个节点都包含一个元素和一个指向下一个节点的指针。要将元素插入列表,只需要以下几点:

  • 创建一个新节点来保存元素;
  • 将前一个节点的下一个指针设置为新节点;
  • 将新节点的下一个指针设置为列表中的下一个元素。
  • 如果你曾经做过一系列回形针,你可以把每一个回形针看作是回形针链的开始,以及其后的所有回形针。要将新的回形针插入链条,只需在新回形针将要插入的位置断开回形针,然后插入新回形针。LinkedList就像一个回形针链。

    ArrayList类似于一个柱箱或一个Mancala板,每个隔间只能容纳一个物品。如果你想在中间插入一个新的元素(并且保持所有元素的顺序相同),你就必须将所有元素都移到该位置之后。

    在链表中给定节点之后的插入是固定时间,只要您已经对该节点引用(在Java中使用EDCOX1×2),到达该位置通常需要在节点的位置上线性时间。也就是说,要到达第n个节点,需要采取n个步骤。在数组列表(或数组,或任何基于连续内存的结构)中,列表中第个元素的地址只是(第一个元素的地址)+n×;(元素的大小),一个小的算术位,我们的计算设备支持对任意内存地址的快速访问。


    我认为,在分析复杂性时,您需要考虑到您使用的度量标准。在ArrayList中,您的度量是shuffling,这只是赋值。但这是一个相当复杂的操作。

    另一方面,您使用的是LinkedList,您只需查看参考。实际上,您只执行1次插入。因此,虽然算法的复杂性最终会相似,但在O(n)时间执行的实际进程是不同的。在ArrayList的情况下,它执行了大量的内存操作。在一个LinkedList的例子中,它只是一个读数。

    对于那些说他不了解LinkedList的人

    LinkedList只在开始处有一个指针,在结束处有一个指针。它不会自动知道要删除的节点后面的节点(除非它是双链接列表),所以您需要遍历该列表,从创建临时指针开始,直到到达要删除的节点之前的节点,我相信OP正在讨论这个问题。