MergeSort是一种分而治之的算法,它将输入分成几个部分并递归地求解这些部分。
......分割功能有几种方法。一种方法是拆分中间。这种方法有一些很好的属性,但是,我们将专注于一个更快一点的方法:奇偶分裂。我们的想法是将每个偶数位置元素放在一个列表中,将每个奇数位置放在另一个列表中。
这直接来自我的讲义。为什么奇偶分裂的速度比阵列中间快?
我猜测它与传入MergeSort的列表有关,并且质量已经已经排序,但我不完全确定。
有人可以对此有所了解吗?
编辑:我尝试在Python中运行以下内容......
global K
K = []
for i in range (1, 100000):
K.append(i)
def testMergeSort():
"""
testMergeSort shows the proper functionality for the
Merge Sort Algorithm implemented above.
"""
t = Timer("mergeSort([K])", "from __main__ import *")
print(t.timeit(1000000))
p = Timer("mergeSort2([K])", "from __main__ import *")
print(p.timeit(1000000))
(MergeSort是奇数MergeSort,MergeSort2将中心分开)
结果是:
0.771506746608
0.843161219237
答案 0 :(得分:1)
我可以看到它可能更好,因为将它与替代元素分开意味着您不必知道输入的开始时间 - 您只需将元素放入交替列表中直到您跑了。
如果您仔细考虑更好的并行处理,那么在完成第一个列表的迭代之前,您可能会开始拆分结果列表。
我应该补充一点,我不是这些问题的专家,他们只是想到的事情......
答案 1 :(得分:1)
输入列表越接近已排序,运行时越低(这是因为如果所有值都已正确,merge
过程不需要move
任何值它只是执行 O ( n )比较。由于MergeSort在分割的每一半上递归调用自身,因此需要选择增加的split
函数列表生成的一半的可能性是按排序顺序排列的。如果列表主要排序,偶数奇数拆分将比分割中间更好。例如,
MergeSort([2, 1, 4, 3, 5, 7])
会导致
Merge(MergeSort([2, 1, 4]), MergeSort([3, 5, 7]))
如果我们拆分中间(注意两个子列表都有排序错误),而如果我们做了偶数 - 奇数拆分我们会得到
Merge(MergeSort([2, 4, 5]), MergeSort([1, 3, 7]))
导致两个已经排序的列表(以及对MergeSort
的后续调用的最佳情况)。但是,在不了解输入列表的情况下,分割函数的选择不应该渐近地影响运行时。
答案 2 :(得分:0)
我怀疑你的实验中有噪音。 :)其中一些可能来自比较和交换实际上没有移动列表中的任何元素,这避免了缓存失效等。
无论如何,这里有一个关于此的聊天:https://cstheory.stackexchange.com/questions/6732/why-is-an-even-odd-split-faster-for-mergesort/6764#6764(是的,我确实在那里发布了类似的答案(完全披露))
相关的维基百科文章指出mergesort是O(n log(n))而Odd-Even Merge Sort是O(n log(n)^ 2)。 Odd-Even肯定是“慢”,但排序网络是静态的,所以你总是知道你将要执行什么操作和(查看维基百科条目中的图形)注意算法如何保持平行直到最后。
当合并排序最终合并2个列表时,Odd-Even合并排序的8元素排序网络的最后比较仍然是独立的。