当我对一些具有许多重复元素的数据进行排序时,快速排序算法效率低下。任何人都可以解释原因吗? 这是我的快速排序代码:
int partition(int arr[],int low,int high)
{
int i = low + 1;
int j = high;
int tmp = arr[low];
while(1)
{
while(j != low && arr[j] > tmp) --j; //from right to left
while(i != high && arr[i] <= tmp) ++i; //from left to right
if(i < j)
{
int t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
else
break;
}
return j;
}
void QuickSort(int arr[],int low,int high)
{
if(low < high)
{
int j = partition(arr,low,high);
int t = arr[j];
arr[j] = arr[low];
arr[low] = t;
if(low < j)
QuickSort(arr,low,j-1);
if(high > j)
QuickSort(arr,j+1,high);
}
}
答案 0 :(得分:3)
我的通灵调试技巧告诉我,你的输入不仅有很多重复,而且重复的元素是连续的,这使得输入大多数都是从开始排序的。一个主要是排序的容器是快速排序的最坏情况,性能降低到O(n^2)
的差。
对于大多数有序输入,其他排序如堆排序和合并排序将提供更好的性能,因为它们的最坏情况只是在它们的平均情况下更高的常数。
答案 1 :(得分:1)
下面的示例快速排序代码类似于问题中的示例代码,但如果有更多重复项则花费的时间更少,如果数据已经排序或反向排序,则最快。主要区别在于使用修改的Hoare分区方案(动态枢轴)和中间值3来选择初始枢轴。应该仍然存在导致最坏情况表现的模式,但我不确定这些模式会是什么。
http://en.wikipedia.org/wiki/Quicksort#Hoare_partition_scheme
void QuickSort(uint32_t a[], int lo, int hi) {
int i = lo, j = (lo + hi)/2, k = hi;
uint32_t pivot;
if (a[k] < a[i]) // median of 3
std::swap(a[k], a[i]);
if (a[j] < a[i])
std::swap(a[j], a[i]);
if (a[k] < a[j])
std::swap(a[k], a[j]);
pivot = a[j];
while (i <= k) { // partition
while (a[i] < pivot)
i++;
while (a[k] > pivot)
k--;
if (i <= k) {
std::swap(a[i], a[k]);
i++;
k--;
}
}
if (lo < k) // recurse
QuickSort(a, lo, k);
if (i < hi)
QuickSort(a, i, hi);
}