使用合并排序的比较数

时间:2009-10-04 19:21:39

标签: algorithm mergesort

如果你有5个不同的数字,你需要多少次比较才能使用合并排序对它进行排序?

6 个答案:

答案 0 :(得分:6)

什么阻止你编写合并排序,保持计数器中的比较数,并在[0,1,2,3,4]的所有排列上尝试?

答案 1 :(得分:4)

我觉得这个问题很有意思,所以我决定彻底探索它(在Python中进行一些实验)。

我从here下载了mergesort.py并修改了它,为比较器函数添加了cmp参数。然后:

import collections
import itertools
import mergesort
import sys

class CountingComparator(object):
  def __init__(self):
    self.count = 0
  def __call__(self, a, b):
    self.count += 1
    return cmp(a, b)

ms_histo = collections.defaultdict(int)

for perm in itertools.permutations(range(int(sys.argv[1]))):
  cc = CountingComparator()
  lperm = list(perm)
  mergesort.mergesort(lperm, cmp=cc)
  ms_histo[cc.count] += 1

for c in sorted(ms_histo):
  print "%d %2d" % (c, ms_histo[c])

得到的简单直方图(从长度4开始,就像我开发和调试它一样)是:

4  8
5 16

对于发布的问题,长度为5而不是4,我得到:

5  4
6 20
7 48
8 48

,长度为6(格式更广; - ):

7    8
8   56
9  176
10 288
11 192

最后,长度为7(甚至更宽的格式; - ):

 9   16
10  128
11  480
12 1216
13 1920
14 1280

肯定会有一些完全规则的组合公式潜伏在这里,但我发现很难通过分析或粗略的数字来衡量它可能是什么。有人有建议吗?

答案 2 :(得分:3)

当合并排序两个长度为L1和L2的列表时,我认为最坏情况下的比较数是L1 + L2-1。

  • 最初你有五个1长的名单。
  • 您可以使用 2比较合并两对列表,从而生成长度为2,2和1的列表。
  • 然后你可以将2和1长列表合并为最多另外1 + 2-1 = 2比较,产生2和3长列表。
  • 最后,您将这些列表合并为最多2 + 3-1 = 4次比较

所以我猜答案是8。

这个数字序列导致上述情况: [2],[4],[1],[3],[5] - > [2,4],[1,3],[5] - > [2,4],[1,3,5] - > [1,2,3,4,5]

修改

这是一个天真的Erlang实现。基于此,对于1 ... 5的排列,比较次数为5,6,7或8。

-module(mergesort).

-compile(export_all).


test() ->
  lists:sort([{sort(L),L} || L <- permutations()]).

sort([]) -> {0, []};
sort([_] = L) -> {0, L};
sort(L) -> 
  {L1, L2} = lists:split(length(L) div 2, L),
  {C1, SL1} = sort(L1), {C2, SL2} = sort(L2),
  {C3, RL} = merge(SL1, SL2, [], 0),
  {C1+C2+C3, RL}.

merge([], L2, Merged, Comps) -> {Comps, Merged ++ L2};
merge(L1, [], Merged, Comps) -> {Comps, Merged ++ L1};
merge([H1|T1], [H2|_] = L2, Merged, Comps) when H1 < H2 -> merge(T1, L2, Merged ++[H1], Comps + 1);
merge(L1, [H2|T2], Merged, Comps) -> merge(L1, T2, Merged ++[H2], Comps + 1).


permutations() ->
  L = lists:seq(1,5),
  [[A,B,C,D,E] || A <- L, B <- L, C <- L, D <- L, E <- L, A =/= B, A =/= C, A =/= D, A =/= E, B =/= C, B =/= D, B =/= E, C =/= D, C =/= E, D =/= E].

答案 3 :(得分:2)

答案 4 :(得分:1)

根据Wikipedia在最坏的情况下,合并排序进行的比较量等于或略小于(n⌈lgn⌉ - 2 ^⌈lgn⌉+ 1)

答案 5 :(得分:0)

对于仅排序的五个不同数字,您可以拥有的最大比较数为8,最小比较数为7.这就是原因: -

假设数组是a,b,c,d,e

递归地划分:a,b,c和d,e

递归地划分:a,b&amp; c和d&amp; e

递归划分:a&amp; b&amp; c和d&amp; e

现在,合并需要进行比较 -

a&amp; b:形成a,b的一个比较

a,b&amp; c:两次比较形成a,b,c

d&amp; e:形成d,e

的一个比较

a,b,c和d,e:最坏情况下的四次比较或三次比较id d是形成a,b,c,d,e的数组的最大元素

因此,在最坏情况下,比较总数将为8,在最佳情况下为7。