c ++快速排序运行时间

时间:2010-04-29 13:12:49

标签: c++ performance quicksort

我对快速排序算法有疑问。我实现快速排序算法并播放它。 初始未排序数组中的元素是从特定范围中选择的随机数。 我发现随机数的范围会影响运行时间。例如,从范围(1 - 2000)中选择的1,000,000随机数的运行时间需要40秒。如果从范围(1 - 10,000)中选择的1,000,000数字需要9秒。 但我不知道如何解释它。在课堂上,我们谈论枢轴值可以影响递归树的深度 对于我的实现,数组的最后一个值被选为透视值。我不使用随机方案来选择枢轴值。

int partition( vector<int> &vec, int p, int r) {

  int x = vec[r];
  int i = (p-1);
  int j = p;
  while(1) {

    if (vec[j] <= x){
      i = (i+1);
      int temp = vec[j];
      vec[j] = vec[i];
      vec[i] = temp;
    }
    j=j+1;
    if (j==r)
      break;
 }
  int temp = vec[i+1];
  vec[i+1] = vec[r];
  vec[r] = temp;
  return i+1;
}

void quicksort ( vector<int> &vec, int p, int r) {

  if (p<r){
    int q = partition(vec, p, r);
    quicksort(vec, p, q-1);
    quicksort(vec, q+1, r);
  }
}

    void random_generator(int num, int * array) {

      srand((unsigned)time(0)); 
      int random_integer; 
      for(int index=0; index< num; index++){ 
        random_integer = (rand()%10000)+1; 
        *(array+index) = random_integer; 
      } 
    }

    int main() {
      int array_size = 1000000;
      int input_array[array_size];
      random_generator(array_size, input_array);
      vector<int> vec(input_array, input_array+array_size);

      clock_t t1, t2;
      t1 = clock();
      quicksort(vec, 0, (array_size - 1));   // call quick sort
      int length = vec.size();
      t2 = clock();
      float diff = ((float)t2 - (float)t1);
      cout << diff << endl;
      cout << diff/CLOCKS_PER_SEC <<endl;
    }

3 个答案:

答案 0 :(得分:5)

很可能它表现不佳,因为quicksort不能很好地处理大量重复项,并且仍然可能导致交换它们(不保证保持键等元素的顺序)。您会注意到,每个数字的重复数量为10000表示10000或500表示2000,而时间因素也约为5。

您是否已将每个尺寸的运行时间平均至少5-10次运行,以便为获得良好的起点提供合理的投射?

作为比较,您是否检查了std :: sort和std :: stable_sort如何在相同的数据集上执行?

最后对于这种数据分布(除非这是一个快速排序练习)我认为计数排序会好得多 - 40K内存来存储计数并且它以O(n)运行。

答案 1 :(得分:0)

这可能与输入的排序程度有关。如果输入是合理随机的,则Quicksort为O(n logn)。如果它的顺序相反,性能会降低到O(n ^ 2)。您可能越来越接近使用较小数据范围的O(n ^ 2)行为。

答案 2 :(得分:0)

最新答案-重复项的效果取决于分区方案。问题中的示例代码是Lomuto分区方案的一种变体,由于分区的恶化,随着重复数的增加,它花费了更多的时间。在所有元素相等的情况下,Lomuto每次递归级别仅将大小减少1个元素。

如果改为使用Hoare分区方案(以中间值作为枢轴),则通常随着重复次数的增加而花费较少的时间。由于重复,Hoare会不必要地交换等于枢轴的值,但是分区将接近将数组拆分为几乎相等大小的部分的理想情况。交换开销在某种程度上被内存缓存掩盖了。链接到Hoare分区方案的Wiki示例:

https://en.wikipedia.org/wiki/Quicksort#Hoare_partition_scheme