使用ArrayList执行优先级队列

时间:2014-06-02 19:23:31

标签: java performance arraylist

我目前正在处理一个最小优先级队列,该队列在添加项目时会自行排序。建议的实现将新项添加到已排序的ArrayList的末尾,然后通过列表返回以查找项正确的位置。因此,它与列表中的每个前一个元素交换,直到添加的项目按顺序排列。

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

我试图理解2之间的性能差异。我理解如果我插入,则必须纠正所有尾随索引(由类方法处理)。但这是否比在列表中交换效率低得多?

提前感谢任何解释

1 个答案:

答案 0 :(得分:1)

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

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

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

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

并说你要插入3

您的初始实施将是这样的:

  1. 找到要插入的索引。 3次比较找到index == 2
  2. 在index处移位元素> 2. 2操作:在一个地方转换5,在一个地方转4。 (这可能是一个操作,具体取决于System.arraycopy()的实现方式)。结果为{1, 2, 0, 4, 5}
  3. 插入元素。 1操作。最终结果为{1, 2, 3, 4, 5}
  4. 总计: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比较。不需要交换。完成。
    7. 总计:3次比较,7次操作。

      作为旁注,您可能最好使用二分搜索来查找插入点而不是直线搜索。