【问题标题】:Heap sort running time堆排序运行时间
【发布时间】:2015-01-28 08:05:48
【问题描述】:

我上次在比较插入排序的两种不同实现的运行时间时发布了一个类似的问题。我现在也有类似的问题。我知道堆排序的复杂度是 O(nlogn),与一般情况下的快速排序相同。但这是我对随机生成的大小为 10,000 的整数数组进行排序时的结果。

快速排序:执行时间:0.005288

堆排序:执行时间:0.234245

如您所见,我的堆排序花费的时间比应有的要多。

这是我的 max_heapify、build_max_heap 和 heapsort 函数的代码:

void max_heapify(int *a,int n,int i)
{
    int largest = 0;

    if((2*i)<=n && a[2*i] > a[i]) largest = 2*i;
    else largest = i;

    if((2*i+1)<=n && a[2*i+1] > a[largest]) largest = 2*i+1;

    if(largest != i) 
    {
        swap(a[i],a[largest]);
        max_heapify(a,n,largest);
    }
}

void build_max_heap(int *a,int n)
{
    for(int i=1;i<=n/2;i++)
    {
        max_heapify(a,n,i);
    }
}

void heapsort(int *a,int n)
{   

    while(n>0)
    {
        build_max_heap(a,n);
        swap(a[1],a[n--]);
    }
}

谁能告诉我实施中的缺陷?该代码有效。我亲自针对较小的样本量对其进行了测试,但效率不高。

感谢任何帮助。谢谢!

【问题讨论】:

  • 尝试对 许多 组随机数据运行这些,并查看平均值。
  • @ScottHunter 问题是,无论您怎么看,运行时间都与应有的时间相差甚远。两种 O(nlogn) 排序算法的运行时间应该不会有这么大的差异。
  • 仅仅因为两种算法具有相同的时间复杂度,并不能保证它们具有相同的运行时间。他们的运行时间很可能会有所不同。
  • 您是否尝试过分析。例如,您可能会在 heapify 上花费大量时间。

标签: algorithm sorting heap quicksort heapsort


【解决方案1】:

我猜重复的 build_max_heap() 是缺陷。 Heapsort 构建一次堆树,然后重复删除根节点中的最大元素。
wikipedia 中的GIF Animation 是一个很好理解的示例。
我用随机字符串评估了 3 种算法。 N=100,000

qsort(3)      usec = 54011  call = 0        compare = 1536365  copy = 0
qsort_trad()  usec = 67603  call = 99999    compare = 2368481  copy = 1344918
heap_sort()   usec = 88814  call = 1624546  compare = 3019351  copy = 1963682

qsort(3) 是 GNU C 库中的索引排序合并排序。 qsort_trad() 是传统的 3 中位数快速排序。 heap_sort() 是我的实现。
概要与 qsort(3) 相同。

【讨论】:

  • 好的。我将尝试构建堆而不重复调用它。谢谢!
【解决方案2】:

FWIW - 我发现对 30000 个元素进行排序时会产生一些乱序的元素。

void check(const int *a, int n)
{     
      int i=1;
      for(i=1; i<n; i++)
      {
         if(a[i]< a[i-1])
         {
            printf("out of order a[%d]=%d a[%d]=%d\n", i,a[i], i-1, a[i-1]);

         }
      }       
}

制作了这个:

out of order a[1]=0 a[0]=1171034357
out of order a[29989]=2147184723 a[29988]=2147452680
out of order a[29991]=2146884982 a[29990]=2147187654
out of order a[29993]=2145044438 a[29992]=2147179272
out of order a[29995]=2145040183 a[29994]=2146044388
out of order a[29996]=2130746386 a[29995]=2145040183
out of order a[29997]=2062733752 a[29996]=2130746386
out of order a[29998]=2026139713 a[29997]=2062733752
out of order a[29999]=1957918169 a[29998]=2026139713

分析:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total
 time   seconds   seconds    calls  ms/call  ms/call  name
 42.57      1.06     1.06                             _mcount_private
 28.11      1.76     0.70 225000000     0.00     0.00  max_heapify
 19.68      2.25     0.49                             __fentry__
  9.64      2.49     0.24    30000     0.01     0.03  build_max_heap
  0.00      2.49     0.00   427498     0.00     0.00  swap
  0.00      2.49     0.00        1     0.00     0.00  check
  0.00      2.49     0.00        1     0.00   940.00  heapsort

从分析中忽略 _mcount_private。

考虑: 1. 确保您的代码正常工作。 2.然后担心执行速度。 3 @ScottHunter (+1) 是正确的 - 你的分析是有缺陷的,所以在同样的意义上是上面的配置文件。

关于不同的 30000 个随机数集的第二个配置文件:

$ ./heapsort
out of order a[1]=0 a[0]=1451707585
out of order a[29989]=2147418839 a[29988]=2147447414
out of order a[29990]=2147336854 a[29989]=2147418839
out of order a[29991]=2147314086 a[29990]=2147336854
out of order a[29992]=2147202205 a[29991]=2147314086
out of order a[29993]=2147177981 a[29992]=2147202205
out of order a[29994]=2133236301 a[29993]=2147177981
out of order a[29996]=2100055600 a[29995]=2137349904
out of order a[29998]=2044161181 a[29997]=2108306471
out of order a[29999]=1580699248 a[29998]=2044161181

Owner@Owner-PC ~
$ gprof heapsort | more
Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total
 time   seconds   seconds    calls   s/call   s/call  name
 45.20      1.13     1.13                             _mcount_private
 30.00      1.88     0.75 225000000     0.00     0.00  max_heapify
 13.20      2.21     0.33                             __fentry__
 11.60      2.50     0.29    30000     0.00     0.00  build_max_heap
  0.00      2.50     0.00   427775     0.00     0.00  swap
  0.00      2.50     0.00        1     0.00     0.00  check
  0.00      2.50     0.00        1     0.00     1.04  heapsort

【讨论】:

    【解决方案3】:
    1. 您正试图根据一个单个随机样本(无论样本中有多少元素)做出判断,这极端不可靠。

    2. 差异可能是由于算法之外的代码造成的(可能第一次算法运行需要时间来初始化不需要为第二次再次初始化的东西)。这也可以通过运行多个样本来解决(例如,通过在算法之间交替)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-26
      相关资源
      最近更新 更多