【问题标题】:Runtime of arraylist operations add and remove by index [duplicate]arraylist 操作的运行时按索引添加和删除 [重复]
【发布时间】:2016-10-02 17:50:13
【问题描述】:

对于 Java ArrayList,是否准确地说按索引添加和删除以摊销的常数时间运行,这意味着平均是常数时间(在极少数情况下通过设置内存为线性时间,以便未来的操作更快)?

【问题讨论】:

  • 是的,但这似乎不是基于索引的。我说的只是索引。
  • ArrayList 和 LinkedList 方法的一般性能在this answer 中回答。它还包含在索引处添加元素,或在索引处删除元素。

标签: java arraylist time-complexity asymptotic-complexity


【解决方案1】:

不,如果说按索引从ArrayList 中插入和删除元素是摊销常数时间,这并不准确,因为复制数据时不会进行摊销。

只有列表扩展及其相关的复制会被摊销,因为它们很少发生*。但是,这需要在列表末尾插入。

当您在列表开头插入时,扩展仍然是摊销的,但每次调用都会发生将元素移动 1 个位置所需的副本,并且摊销。

* 为了能够摊销操作成本,您需要混合使用“便宜”和“昂贵”操作。在这种情况下,您可以在所有操作中分摊总成本,从而获得更低的结果。

【讨论】:

  • 所以如果我的列表有 100,000 长并且我在中间插入,它需要先移动 500,000 之后的所有内容吗? IE。线性时间?
  • @SeanHill 正确。每次在中间插入时,都会将“尾部”移动一为新元素腾出空间,然后将元素设置为预期值。在n-元素列表的中间插入k元素是O(k*n/2)。
  • 但是如果插入太多则需要额外的时间,以便将整个数组复制到内存中具有 2(n+k) 个连续空闲/空空间的新位置?
  • @SeanHill 是的,但是额外的时间被摊销了,因为每次调用都不会发生数组加倍。 (准确地说,它并没有翻倍,因为 Java 使用的是 1.5 倍)。
  • 但是我们可以将列表初始化为我们想要的任何大小,它预先分配多少空间/它何时触发乘法/为什么是 1.5?
【解决方案2】:

对于add(Object) 是,但对于remove(int index),只有当您删除最后一个元素时它才是恒定时间,否则元素会移动以从数组中间删除任何nulls

基于索引的add(并从非最后一个位置删除)不是摊销常数时间,它们是线性时间。

【讨论】:

  • 我说的只是索引,就像在位置 5 中添加这个对象
  • @SeanHill 查看编辑。
  • 那么等等添加对象是不是线性的?或者这更像是一个追加到末尾,除非列表容量加倍,否则它是恒定时间?
  • 这不是“喜欢”,add() 附加到末尾。除非需要调整数组的大小,否则它是恒定的。
  • 我必须再次检查,但我认为有一个 add (object, index) 方法,其中 add 用作插入
猜你喜欢
  • 1970-01-01
  • 2014-07-06
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 2021-10-02
  • 2012-02-24
  • 2021-11-16
  • 1970-01-01
相关资源
最近更新 更多