Java 在ARAYLIST与LIKEDLIST中间插入

Java 在ARAYLIST与LIKEDLIST中间插入,java,performance,arraylist,insert,linked-list,Java,Performance,Arraylist,Insert,Linked List,在Java的上下文中交谈。如果我想插入 > ARARYLIST/或链接目录> /代码>,我已经被告知 ARARYLIST/将执行得非常糟糕。 我理解这是因为,我们需要移动所有元素,然后进行插入。其顺序应为n/2,即O(n) 但是链接列表不也是这样吗。对于链表,我们需要遍历直到找到中间位置,然后执行指针操作。在这种情况下,也需要O(n)时间。不是吗 谢谢这里的原因是链表中的元素没有实际的移动。链表由节点组成,每个节点都包含一个元素和指向下一个节点的指针。将元素插入列表只需要几件事: 创建一个新节点

在Java的上下文中交谈。如果我想插入<代码> > ARARYLIST/<代码>或<代码>链接目录> /代码>,我已经被告知<代码> ARARYLIST/<代码>将执行得非常糟糕。

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

但是
链接列表
不也是这样吗。对于链表,我们需要遍历直到找到中间位置,然后执行指针操作。在这种情况下,也需要O(n)时间。不是吗


谢谢

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

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

    ArrayList
    有点像一个或多个隔间,每个隔间只能容纳一个项目。如果你想在中间插入一个新的元素(并且保持所有元素的顺序相同),那么你必须在那个点之后移动所有的东西。
    链表中给定节点之后的插入是恒定时间,只要您已经有了对该节点的引用(在Java中使用
    ListIterator
    ),并且到达该位置通常需要节点位置的线性时间。也就是说,要到达第n个节点需要n个步骤。在数组列表(或数组,或任何基于连续内存的结构)中,列表中第n个元素的地址只是(第一个元素的地址)+n×(元素大小),这是一个简单的算术运算,我们的计算设备支持快速访问任意内存地址。

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

    另一方面,您使用的是
    链接列表
    ,您只需查看引用即可。实际上,您只执行一次插入。因此,虽然算法复杂度将类似,但在
    O(n)
    时间执行的实际过程是不同的。对于
    ArrayList
    ,它执行大量内存操作。对于
    链接列表
    ,它只是在读取

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


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

    可能更适合程序员StackExchangeArrayList和
    LinkedList
    的位插入都是O(n)(对于平均性能和最差性能)。接下来的问题是哪个系数更大。配置文件并查找。@dardo-这里很好。。。IMOI并不是说它不能在这里回答,只是说它可能会对程序员产生更多的关注。而<>代码> ARARYList试图总是有大约10个空元素来处理扩展,所以通过插入中间,它将数组克隆到元素重新排序的另一个数组上。@ RichardTingle就是我制作的那个点。每当使用
    ArrayList
    时,它必须对元素重新排序并克隆它。因此,对于这个“简单”的任务,要执行的操作要多得多。@Joshua Taylor,但无论如何,您都需要遍历列表直到插入点。成本高昂的是
    转换过程吗?如果是,你能告诉我为什么是这样吗。?因为否则,即使是LinkedList也需要n/2个步骤才能到达列表的中间位置来进行插入。@Kraken您忘记了每次向
    ArrayList
    添加元素时,它必须创建一个全新的
    ArrayList
    并克隆所有元素。它通过迭代内部化的数组来实现这一点。因此,这比使用某种链表简单地更改两个引用要复杂得多。@SnakeDoc您可以在数组中预先分配空间并决定何时这样做(使用
    ensureCapacity
    )。此外,我所关注的JDK在需要重新分配时将增长1.5倍。