假设我们有一个未排序的列表[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吗?
答案 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