在ArrayList和LinkedList中间插入元素

29 浏览
0 Comments

在ArrayList和LinkedList中间插入元素

这个问题在这里已经有答案了:

在Java中何时使用LinkedList而不是ArrayList?

在Java的上下文中谈论。如果我想在 ArrayListlinkedList 的中间插入元素,有人告诉我 ArrayList 的性能会非常糟糕。

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

但是对于 linkedList,难道不是一样吗?对于链表,我们需要遍历直到找到中间点,然后进行指针操作。在这种情况下,也需要O(n)的时间,不是吗?

谢谢

admin 更改状态以发布 2023年5月22日
0
0 Comments

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

另一方面,你使用了一个 LinkedList,你只是去到了这个引用。实际上,你只执行了一次插入操作。因此,虽然算法复杂度最终会相似,但实际上在 O(n) 时间内执行的进程是不同的。在 ArrayList 的情况下,它执行了许多内存操作。在 LinkedList 的情况下,它只是读取。

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

LinkedList 只有一个指向开头的指针和一个指向结尾的指针。除非它是双向链表,否则它不会自动知道你要删除的节点后面的节点,因此你需要通过创建一个临时指针从开头遍历列表,直到你到达要删除的节点之前的节点,我认为这就是 OP 正在讨论的问题。

0
0 Comments

原因在于链表中没有实际的元素移位。链表是由节点构成的,每个节点包含一个元素和指向下一个节点的指针。要将一个元素插入列表中,只需要几个步骤:

  1. 创建一个新的节点来保存元素;
  2. 将上一个节点的下一个指针设置为新节点;
  3. 将新节点的下一个指针设置为列表中的下一个元素。

如果你曾经制作过一个纸夹链,你可以将每个纸夹视为它及其后面的所有纸夹的开头。要在链中插入新的纸夹,你只需要在新纸夹将插入的位置处断开链,并插入新纸夹。链表就像一个纸夹链。

ArrayList 类似于一个药盒或曼卡拉棋盘,每个隔间只能容纳一个物品。如果你想在中间插入一个新的元素(并保持所有元素的顺序),你将不得不移动那个位置之后的所有元素。

在链表中给定节点后的插入是常数时间,只要你已经有了对该节点的引用(在 Java 中使用 ListIterator),而到达该位置通常需要与节点位置成线性的时间。也就是说,要到达第 n 个节点需要 n 步。在一个数组列表(或数组,或任何基于连续内存的结构)中,列表中第 n 个元素的地址只是(第一个元素的地址)+n×(元素大小),这是一种微不足道的算术运算,我们的计算设备支持快速访问任意的内存地址。

0