没有额外的数据结构/常量空间限制:
您描述的算法本质上是选择排序。O(n2)
如果您可以访问某种迭代器(如果没有,您将如何访问集合中的元素?),我相信使用自定义合并排序可以做得更好,如下所示:
比较元素 1 和 2。removeAndAppend
较小的元素,然后removeAndAppend
是剩余的元素。对元素 3 和 4、5 和 6,...以及元素 n-1 和 n 执行相同的操作。
现在,您将对每个包含 2 个元素的子集合进行排序。
合并索引 (1,2) 和 (3,4)。为此,从头开始有 2 个迭代器。首先将一个增加两次。removeAndAppend
然后像往常一样使用该函数进行合并排序。对 (5,6) 和 (7,8)、(9,10) 和 (11,12)、... 和 (n-3,n-2) 和 (n-1,n) 执行相同操作。
现在您将对每个包含 4 个元素的子集合进行排序。
合并与上述类似的大小 4 的集合,然后合并 8、16、32 等,直到达到集合大小。
整个过程将如下所示:
// setSize is how large sets we're currently merging
for setSize = 1; setSize <= n/2; setSize *= 2
iterator left = begin
right = begin
for pos = 1 to n/(2*setSize)
// here right and left are both at the beginning
// even after the previous iteration of the loop,
// since we've removed and appended all other elements
// so we only need to increase right by setSize
right += setSize
for i = 1 to 2*setSize
if (left.value <= right.value)
removeAndAppend(left)
else
removeAndAppend(right)
以上只是一个基本的草稿,它可能不是 100% 正确的,并且没有考虑到集合不是 2 的幂(这种情况经常发生)。在这种情况下你需要小心,否则你可能会绕回,或者走得不够远,最终得到一个部分排序的集合。
复杂性分析应该与常规合并排序几乎相同,并导致O(n log n)
运行时间。
使用额外的数据结构/没有常量空间限制:
将所有元素提取到另一个集合中,对其进行排序O(n log n)
(使用您选择的排序算法)并遍历排序集,removeAndAppend
为每个集合调用原始集合。
如果您不允许提取元素,则仍然可以通过使用索引集合来使用此方法,并且要进行比较,只需查找适用的元素即可。但是,为了提高效率,您需要按索引进行恒定时间查找。