我有一个经常插入排序的列表。是否有一个好的位置(除了结尾)添加到此列表以最小化插入排序必须做的工作?
答案 0 :(得分:2)
插入的最佳位置是元素属于排序列表的位置。这类似于抢先插入排序。
答案 1 :(得分:1)
你的问题没有意义。列表是插入排序的(这意味着你不能按定义附加到末尾;元素仍然会在它所属的位置结束。否则,列表将不会被排序)。
如果你必须添加许多元素,那么最好的解决方案是克隆列表,添加所有元素,对新列表进行一次排序,然后用克隆替换第一个列表。
[编辑]回复你的评论:做了几个追加后,你必须先对列表进行排序,然后才能进行下一次排序。所以问题不在于如何使分类插入更便宜,而是在追加和分类插入之间进行排序。
答案是大多数排序算法对部分排序列表的效果非常好。您需要问的问题是:使用什么排序算法,它具有哪些属性,最重要的是,您应该关注的原因。
最后一个问题意味着你应该在进行任何类型的优化之前测量性能,因为除非它基于实际数字,否则它有90%的可能性会比它有所帮助。
回到排序。 Java使用quicksort版本对集合进行排序。 Quicksort将选择一个pivot元素来对集合进行分区。该选择对于算法的性能至关重要。为获得最佳性能,枢轴元素应尽可能靠近结果中间的元素。通常,quicksort使用当前分区中间的元素作为pivot元素。此外,quicksort将开始使用小索引处理列表。
因此,最后添加新元素可能无法为您提供良好的性能。它不会影响枢轴元素选择,但quicksort将在检查了所有已排序元素后查看新元素。在中间添加新元素将影响枢轴选择,我们无法确定这是否会对性能产生影响。我的本能猜测是,如果quicksort在分区中间找到已排序的元素,则pivot元素会更好。
在开头添加新元素。这样,quicksort通常会找到一个完美的枢轴元素(因为列表的中间将被排序),它将首先获取新的元素。缺点是您必须为每个插入复制整个数组。有两种方法可以避免这种情况:a)As I said elsewhere,今天的PC几乎没有时间复制大量的RAM,所以你可以忽略这个小的性能损失。 b)您可以使用第二个ArrayList,将所有新元素放入其中,然后使用addAll()
。对于这种情况,Java将在内部进行一些优化,只需移动现有元素一次。
[EDIT2]我完全误解了你的问题。对于算法insertion sort,最好的地方可能在中间的某个地方。这应该使您必须将元素移动到整个列表的几率减半。但由于我不是100%肯定,我建议创建几个小测试来验证这一点。