Shell排序最坏的情况时间复杂度

时间:2015-09-18 17:10:58

标签: java algorithm performance shell time-complexity

我想通过此代码了解shell排序的最坏情况分析。你能帮助我找出来吗? while循环将执行 O(log n) 次,for循环 O(n) 次;那么复杂性如何变成 O(n^2) 呢?一个完整的答案将不胜感激;我已经被困在这一天了。

int i, n = a.length, diff = n/2, interchange, temp;
while (diff > 0) 
{ 
  interchange=0;
  for (i = 0; i < n - diff; i++) 
  {
    if (a[i] > a[i + diff]) 
    { 
      temp = a[i];
      a[i] = a[i + diff];
      a[i + diff] = temp;
      interchange = 1;
    }
  }

  if (interchange == 0) 
  {
    diff = diff/2;
  }
}

2 个答案:

答案 0 :(得分:2)

您的算法不是shell排序。 Shell排序通过多次执行基本冒泡排序来工作。每次,您只考虑它们之间有k个元素间隙的元素。 k由以1结尾的递减序列给出。您的序列是n / 2,n / 4,n / 8,...,1,这很好。但是你没有为这个序列的每个成员执行冒泡排序;你只进行一次传球,这还不够。 O(n ^ 2)的最坏情况复杂性是由于冒泡排序。

请注意,在您的情况下,由于序列没有恒定长度,如果您修复算法,最坏情况下的复杂度将为O(n ^ 2 * logn)。

有关该算法的详细信息,wikipedia是您的朋友。

稍后编辑:

更正的代码是:

int i,n=a.length,diff=n/2,interchange,temp;
 while(diff>0) { 
 interchange=0;
 for(i=diff; i<n;i++) {
    temp=a[i];
    for (j = i; j >= gap && a[j-gap] > temp; j -= gap)
      a[j] = a[j-gap];  
    a[j]=temp;
  }
  diff=diff/2;
 }

请注意我没有检查,所以我可能错了。现在,你能看到嵌套的for循环使复杂性为O(n ^ 2)吗?

答案 1 :(得分:0)

您正在考虑的问题是您对平均情况和最坏情况感到困惑。在一般情况下,diff将定期更新并进行除法,从而导致while循环执行接近lgn次。但是,由于数据被交换,您有可能每个循环交换变为1。如果数据以最糟糕的方式排序,则每个循环都将移动数据。这将导致while循环执行n次而不是lgn。将while循环和for循环都放在o(n)处,你看o(n ^ 2)

考虑使用数字排序长度为4的数组:4,3,2,1。

第一个循环,你找到并切换4和2,以及3和1.这使你的循环:2,1,4,3。

下一个循环,没有任何反应,互换是0,所以它将你的差异减半。

第三循环,你找到并切换2和1,以及4和3:1,2,3,4

交换是1,差异仍然是1,所以你做另一个循环。没有任何事情发生,并且差异变为0.5退出你的循环。

在这种情况下,while循环执行n次,for循环执行n次。