C++ 迭代式就地合并排序

C++ 迭代式就地合并排序,c++,algorithm,sorting,mergesort,C++,Algorithm,Sorting,Mergesort,对于我的算法类,我们的任务是编写一个合并排序的实现,它是迭代的而不是递归的,并且不需要另一个数组。因为这是一个类,我不想给我任何代码,但我不能找出做什么的基本算法。谷歌搜索除了代码或者我不理解的解释之外,没有提供任何东西,所以这没有帮助 我目前理解的是对大小为1的所有子数组进行排序(这当然很简单),然后合并大小为2、大小为4的子数组,等等,但这似乎更接近插入排序,然后是如何使用恒定的额外空间的问题 最后,我不允许使用任何C++标准库函数或类,例如向量、栈、任何种类等。< P>一种迭代算法,它使用

对于我的算法类,我们的任务是编写一个合并排序的实现,它是迭代的而不是递归的,并且不需要另一个数组。因为这是一个类,我不想给我任何代码,但我不能找出做什么的基本算法。谷歌搜索除了代码或者我不理解的解释之外,没有提供任何东西,所以这没有帮助

我目前理解的是对大小为1的所有子数组进行排序(这当然很简单),然后合并大小为2、大小为4的子数组,等等,但这似乎更接近插入排序,然后是如何使用恒定的额外空间的问题


最后,我不允许使用任何C++标准库函数或类,例如向量、栈、任何种类等。

< P>一种迭代算法,它使用一种“类型”合并排序来排序数组。 让我们以这个未排序的数组为例:

4, 3, 8, 5, 9, 2, 5, 1, 7, 10, 8, 0, 3
该算法将在合并数组的大小上有一个外循环。因此,在开始时,该大小为1(尚未合并任何内容)。然后在每次迭代中,这个大小加倍,这有效地将两个已经排序的连续段合并在一起

实际合并将在要合并的段中使用两个索引:一个位于要合并的两个段的开头

只要左索引处的值小于或等于另一个值,左索引就会递增(向右移动)。在另一种情况下,执行该算法中最复杂的操作:

两个索引之间的值向右移动,最右边的值(第二个索引处的值)移动到第一个索引。因此,这些值围绕一个位置循环。在此循环之后,两个索引都将递增

重复此过程,直到左索引到达右索引,或右索引到达第二段的末尾(可以是数组的末尾)。当这种情况发生时,合并完成,在外循环的下一次迭代中将这两个段视为一个

以下是一些图像,说明了将在示例数据上执行的这些步骤:

此处执行合并以生成大小为2的段。有时,最后一段不会有完整的大小,但这不是问题。对于每个彩色段,放置两个索引,一个指向两个值中的第一个,另一个指向第二个值。如果第一个值大于第二个值,则交换它们。在交换的情况下,两个索引都递增,第二个索引到达第二个段的末尾(该段只有1个值宽),因此合并结束。如果没有交换,只有第一个索引会增加,但会到达第二个索引,因此合并也会结束(没有进行更改)

在外循环的第二次迭代中变得更有趣:

第一个要连接的段是[3 4]和[5 8]。这两个索引分别指向3和5(蓝色下划线)。只要对应的值不大于第二个索引的值,左索引就会递增。在这种情况下,这意味着第一个索引到达第二个索引时没有任何更改。对于第二对分段,还有更多工作要做:

现在需要合并[29]和[15]。当2大于1时,循环操作开始:1必须移入,将2和9向右推一个位置。两个索引都是递增的。现在2不大于另一个值(5),因此只增加第一个索引。最后,9大于5,因此它们需要交换,然后这些段的合并完成

对下一对段执行类似的操作序列:

最后一个“对”段实际上没有第二个段:第二个索引点超出数组末端,因此合并立即停止

外部循环再次迭代,使段大小加倍。现在必须合并以下内容:

请注意1(在第二个索引处)是如何在[3 4 5 8]之前移入的,所有这些都会向右移动一个位置以为其腾出空间。 2也会发生同样的情况:在再次输入相同的4个值之前,它会被移入。 但是我们发现3不大于5,第一个指数递增,直到它指向8。在这里,5在8之前被注入。 最后,8不大于9,因此第二个索引到达终点

对于另一个片段,以及外循环的最后一次迭代,我将不做同样的介绍,它将进行一次合并

按照您的要求,我不提供任何代码;-)

一些考虑 虽然这可以称为合并排序,但在最坏的情况下,值的循环确实会破坏原始算法的效率。的确,比较的次数仍然相同,但移动的次数可以更多。例如,将值[3 4 5 8]移动两次,以便为移动1和移动2腾出空间。这已经总计10次移动(该步骤中的合并尚未完成),而原始合并排序将始终执行与正在合并的段中的值相同的移动次数。在更好的情况下,该算法完全不需要移动,或者比原始算法更少


这个方法保证了一个稳定的排序。

您提到了固定的空间和位置

如果就地合并排序不一定是稳定的,那么可以交换元素,而不是在数组之间移动它们。对数组的左半部分执行合并排序,将合并的输出与数组的右半部分交换,以便合并的输出最终在数组的右半部分,而数组的右半部分中的内容最终交换到数组的左半部分