【问题标题】:Performance of priority queue using an ArrayList使用 ArrayList 的优先级队列的性能
【发布时间】:2014-06-02 19:23:31
【问题描述】:

我目前正在研究一个最低优先级队列,该队列在添加项目时保持自身排序。建议的实现将新项目添加到排序的 ArrayList 的末尾,然后通过列表返回以找到项目的正确位置。因此它与列表中的每个前一个元素交换,直到添加的项目是有序的。

建议我在此方法之前使用的实现涉及通过排序列表进行比较,标记要插入项目的索引,然后使用 Java 的 add(int index, Object O) 方法,而不是仅仅添加到末尾。

我试图了解两者之间的性能差异。我知道如果我插入,所有尾随索引都必须更正(由类方法处理)。但这真的比通过列表交换回来效率低吗?

提前感谢您的任何解释

【问题讨论】:

  • 那么,在您将元素添加到末尾然后将列表向下交换到正确位置之前?
  • 为什么不使用 TreeSet?
  • @spudone 使用ArrayList的具体要求

标签: java performance arraylist


【解决方案1】:

如上所述,这两个选择都将在 O(n) 时间内运行(我认为)。但是,第二个选项(即您的初始实现)可能具有更好的常数因子,因为一次移动一组元素可能(并且可能会)比一次移动一个元素更有效,特别是如果您必须移动大量元素。所以我会说你的初始实现效率更高,除非你的最终插入点几乎总是靠近数组的末尾,此时System.arraycopy() 的开销可能会主导执行实际工作所需的时间——但不是很多。

我想您可以将这两种情况视为大致比较冒泡排序(建议实现)和插入排序(初始实现)的单次迭代。两者具有相同的时间复杂度,但由于操作较少,插入排序的单次迭代几乎总是(或者可能总是?)运行得更快。

以此为例(为简单起见假设可调整大小的数组):

int[] a = new int[] {1, 2, 4, 5};

并说你想插入3

你的初始实现会是这样的:

  1. 找到要插入的索引。 3 个比较找到index == 2
  2. 在索引 > 2 处移位元素。 2 次操作:将 5 移位一位,将 4 移位一位。 (这可能是一项操作,具体取决于System.arraycopy() 的实现方式)。结果是{1, 2, 0, 4, 5}
  3. 插入元素。 1 操作。最终结果是{1, 2, 3, 4, 5}

总计:3 次比较,3 次操作。

您的新实现将如下所示:

  1. 在末尾插入元素。 1 操作。结果是{1, 2, 4, 5, 3}
  2. 比较看是否需要交换。 1比较。需要交换。
  3. 交换。 3操作:将5分配给临时变量,将3分配给索引3,将临时变量分配给索引4。结果是{1, 2, 4, 3, 5}
  4. 比较看是否需要交换。 1比较。需要交换。
  5. 交换。 3 次操作:将 4 分配给临时变量,将 3 分配给索引 2,将临时变量分配给索引 3。结果为 {1, 2, 3, 4, 5}
  6. 比较看是否需要交换。 1比较。不需要交换。完成。

总计:3 次比较,7 次操作。

附带说明,您最好使用二分查找而不是直线搜索来查找插入点。

【讨论】:

  • 感谢您的详细解释
猜你喜欢
  • 2011-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
相关资源
最近更新 更多