为什么quicksort在按降序排序和升序排序时需要更长的时间

时间:2013-08-19 08:54:58

标签: c++ c algorithm sorting quicksort

我有quicksort和mergesort的代码,并且我已经放置了一个全局计数器变量,该变量在每次迭代(比较)时都会递增。我认为这与我的粗略渐近分析相对应。对于合并排序它确实如此,但对于快速排序它没有。我不明白为什么。我选择输入数组的最后一个元素是每次迭代中的数据透视表。我知道这不是最佳的,但这对于本次讨论并不重要。由于我选择了最后一个元素,我希望升序和降序数组都会导致O(n ^ 2)比较。更具体地说,我希望比较的数量是n选择2,因为在最坏的情况下你要加n + n-1 + n-2 + n-3 + .... + 1。但这似乎并没有发生。

在输入大小为100,000时,输入按降序排序,我得到705,082,704次迭代计数。我得到一个按升序排序的输入数组的相同数字。但100,000选择2约为50亿。为什么会出现差异?

对于合并排序,输入为100,000,我得到大约160万次迭代,这看起来是正确的。

以下是代码,其中包括我的快速排序实施以及我的计数技术,两者都可能会关闭,从而导致这种差异。否则,我的逻辑错误在于应该进行多少次迭代?

另外,另外,我很好奇,尽管升序和降序输入数组的比较次数相同,但升序版本的速度是后者的2-3倍。有什么可以解释的。这里没有进一步的代码。

int counter = 0;
int compare (const void * a, const void * b)
{
    return ( *(int*)a - *(int*)b );
}


int partition(int *array, int low, int high){
  int firsthigh = low;
  int pivot = high;

  for(int i = low; i < high; i++)
  {
    counter++;
    if(array[i] < array[pivot])
    {
      swap(array[i], array[firsthigh]);
      firsthigh++;
    }
  }
  swap(array[pivot],array[firsthigh]);
  return firsthigh;
}

void quicksort(int *array, int low, int high){
  int p;
  if(low < high)
  {
    p = partition(array, low, high);
    quicksort(array, low, p-1);
    quicksort(array,p+1,high);
  }
}

int main(){
  int array[100000];
  for(int i = 0; i < 100000; i++)
    array[i] = i;

  struct timeval start, end;

  for(int i = 0; i < 100000; i++)
    cout << array[i] << " ";

  gettimeofday(&start, NULL);

  //mergesort(array, 0, 99999);
  quicksort(array, 0, 99999);

  gettimeofday(&end, NULL);
  long long time =   (end.tv_sec * (unsigned int)1e6 +   end.tv_usec) -
                     (start.tv_sec * (unsigned int)1e6 + start.tv_usec);

  for(int i = 0; i < 100000; i++)
    cout << array[i] << " ";
  cout << endl;

  cout << endl << endl << time/1000000.0 << endl;
  cout << endl << counter;
}

1 个答案:

答案 0 :(得分:4)

  1. 如果要计算内部for循环的迭代次数,请使用long longn*(n-1)/2溢出了n = 100 000的int。如果你想计算掉期,你应该在交换时增加你的计数器。

  2. 要做的两个简单的优化是:

  3. 当然还有其他一些,但这应该会给你一个不错的算法。