编辑:没关系

时间:2013-04-03 14:54:19

标签: big-o

编辑:哇,我很抱歉......我在某种程度上混淆了第二张图中的LinkedList和ArrayList列> _>我没有多少睡觉....抱歉...至少有一个答案确实以其他方式帮助了我,详细解释,所以这篇文章不是一个完全浪费......

我确实找到了一些关于此的话题,但帖子中存在矛盾,所以我想确认谁是正确的。

这是我发现的主题: When to use LinkedList over ArrayList?

最受欢迎的答案是:

  

“对于LinkedList

     
      
  • get is O(n)
  •   
  • add is O(1)
  •   
  • 删除是O(n)
  •   
  • Iterator.remove是O(1)
  •   
     

对于ArrayList

     
      
  • get is O(1)
  •   
  • add是O(1)摊销,但O(n)最坏情况,因为数组必须调整大小并复制
  •   
  • 删除是O(n)“
  •   

但是其他人在这里发布了一个链接说: http://leepoint.net/notes-java/algorithms/big-oh/bigoh.html

Algorithm     ArrayList   LinkedList
access front     O(1)         O(1)
access back      O(1)         O(1)
access middle    O(1)         O(N)
insert at front  O(N)         O(1)
insert at back   O(1)         O(1)
insert in middle O(N)         O(1)

1 个答案:

答案 0 :(得分:0)

问题中引用的两个来源之间没有矛盾。

首先关于 LinkedLists 的一些想法: 在链表中,我们需要在列表中移动指针以访问任何特定元素,以删除它,检查它或在它之前插入新元素。由于java.util.LinkedList实现包含对列表正面和背面的引用,因此我们可以立即访问列表的正面和背面,这解释了为什么涉及列表前面或后面的任何操作都是O(1 )。如果使用迭代器完成操作,则指针已经是您需要的位置。因此,从中间删除元素花费O(n)时间,但如果迭代器已经花费了O(n)操作到达中间,则iter.remove()可以在O(1)中执行。

现在conisider ArrayList : 在引擎盖下,ArrayList将数据存储在基本数组中。因此,虽然我们可以在O(1)时间内访问任何元素,但添加或删除元素将要求整个数组向下移动一个元素,这需要O(n)时间。如果我们要添加或删除最后一个元素,则不需要任何移位,因此可以在O(1)中运行。

这意味着调用list.add(newItem)需要O(1),但偶尔在列表末尾没有空间,因此需要在ArrayList执行添加之前将整个列表复制到新内存中。但是,由于每次ArrayList调整自身大小都会使之前的容量增加一倍,因此在添加n个元素时,此复制操作仅发生log 2 n次。所以我们仍然说在O(1)时间内添加运行。如果您知道在创建ArrayList时将添加多少元素,则可以通过避免复制操作为其提供初始容量来提高性能。