Shell在预排序列表上排序运行时间(最佳情况)

时间:2012-02-16 22:54:15

标签: algorithm sorting time-complexity

如果列表已预先排序(最好的情况),我对shell排序的运行时间感到困惑。是O(n)还是O(n log n)?

    for(k=n/2; k>0; k/=2)
       for(i=k; i<n; i++)
           for(j=i;j>k; j-=k)
              if(a[j-k]>a[j]) swap
              else break;

Shell排序基于插入排序,插入排序有预先排序列表的O(n)运行时间,但是,通过引入空隙(最外层循环),我不知道它是否使shell的运行时间对预排序列表排序O(n log n)。

感谢您的帮助

3 个答案:

答案 0 :(得分:2)

在数据已经订购的最佳情况下,最内层的循环永远不会交换。它将始终立即中断,因为已知左值小于正确的值:

for(k=n/2; k>0; k/=2)
   for(i=k; i<n; i++)
       for(j=i;j>k; j-=k)
          if(false) swap
          else break;

所以,算法崩溃了:

for(k=n/2; k>0; k/=2)
   for(i=k; i<n; i++)
      no_op()

最好的情况是:

O((n - n/2) + (n - n/4) + (n - n/8) + ... + (n - 1)) 
= O(nlog(n) - n) 
= O(nlog(n))

那就是according to Wikipedia,Shell Sort的其他一些变种确实有O(N)最好的情况。

答案 1 :(得分:1)

我认为(至少正常实施)它大约为O(n log n),但具体数字取决于您使用的进展。

例如,在第一次迭代中,您调用插入排序,比方说,五次,每次排序每五个元素。由于每个元素在排序的元素数量上都是线性的,因此整体上会出现线性复杂度。

在下一次迭代中,您调用插入排序,例如两次,对每个其他元素进行排序。再次,线性整体。

在第三个中,你对每个元素进行插入排序,再次是线性的。

简而言之,你有一个线性算法调用(大致)对数次数,因此它应该大约为O(n log n)。这假设您使用的步长有某种几何级数,这很常见,但(可能)并非绝对必要。

答案 2 :(得分:0)

最好的情况是O(n)。这就是原因:

让我们从插入排序开始。已排序的n个条目列表将需要n-1个比较才能完成(无需交换)。

将插入排序放在具有单个增量的shellort的上下文中.1。已排序的n个条目列表将需要n减去间隙(1)。

假设您有两个间隙5后跟1且n大于5.已经排序的列表将需要n-5个比较来处理第一个间隙(无需交换)以及第二个或2n-的n-1个比较6(无需交换)。

如果使用n作为输入来产生间隙并不重要。最后,每个间隙都是一个常数值c(最终c为1)。

因此,最佳案例的算法是&#34; n *间隙数 - 所有间隙的总和&#34;。

我不知道&#34; n *间隙的数量 - ......&#34;可能是O(n)以外的任何东西。

我知道大多数讨论都把它作为别的东西,我得到的印象是没有人打扰坐下来做数学。如你所见,它不是火箭科学。