为什么我们使用Merge Sort将一半的未排序列表分解?

时间:2018-03-28 19:39:00

标签: sorting big-o mergesort

假设我们有一个未排序的列表[7,10,18,2,9,45]。使用合并排序,我们将其分解为一半

  

[7,10,18,2,9,45]

     

[7,10,18] [2,9,45]

     

[7,10] [18] [2,9] [45]

     

[7] [10] [18] [2] [9] [45]

然后重新开始工作。但是,为什么我们要把它分成两半呢?为什么不首先采用初始未排序列表并立即将其分解为1个元素列表的基本情况,然后通过一次组合其中两个1元素列表进行备份,如下所示:

  

[7,10,18,2,9,45]

     

[7] [10] [18] [2] [9] [45]

为什么要经历将未排序列表减半的所有中间步骤?这会影响大O吗?

3 个答案:

答案 0 :(得分:2)

嗯,这是一个很好的问题,但你正在思考迭代模式。在激活寄存器中,您必须知道mergesort以递归模式中断数组。我的意思是,你以这种方式合并:

  [3,7,4,8,10,9] --> [3] [7] [4] [8] [10] [9]

这是在一组递归模式下完成的,但是如果你以迭代模式调用并用循环分隔所有这些值,那么你在函数中没有状态,因为你有一组被分开的值,但是你在哪里有包含合并所有值的寄存器?您必须考虑寄存器模式保存值,然后取消激活寄存器并合并执行此操作的值:

[3] [7] [4] [8] [10] [9] --->  [3, 7] [4,8] [9, 10]

你注意到了这个变化吗?这是你需要一个递归调用的方式,因为你分解了以前的状态并一次又一次地合并。 我希望我帮助你。

答案 1 :(得分:1)

您需要递归拆分,不仅要将此列表分解为子列表,还要控制列表的合并,因为您需要提交"备份"排序后的子列表。

如果您反而一次迭代地拆分一个元素,然后一次将它们合并回一个元素,那么最终会得到一个O( n 2 )算法而不是O( n log( n ))

答案 2 :(得分:0)

  

为什么不首先采用初始未排序列表并立即将其分解为1个元素列表的基本情况,然后通过一次组合其中两个1元素列表进行备份?

从1个元素列表(运行)的基本情况开始,是如何完成自下而上的迭代合并排序。它的速度稍快,因为索引对不会被推入堆栈并从堆栈中弹出。大多数库使用自下而上合并排序的一些变体。 Wiki文章包含伪代码:

https://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation