快排注意点
选择基准元的方式
方法1 固定基准元
如果输入序列是随机的,处理时间是可以接受的。如果数组已经有序时,此时的分割就是一个非常不好的分割。因为每次划分只能使待排序序列减一,此时为最坏情况,快速排序沦为冒泡排序,时间复杂度为Θ(n^2)。而且,输入的数据是有序或部分有序的情况是相当常见的。因此,使用第一个元素作为基准元是非常糟糕的,应该立即放弃这种想法。
方法2 随机基准元
这是一种相对安全的策略。由于基准元的位置是随机的,那么产生的分割也不会总是会出现劣质的分割。在整个数组数字全相等时,仍然是最坏情况,时间复杂度是O(n2)。实际上,随机化快速排序得到理论最坏情况的可能性仅为1/(2n)。所以随机化快速排序可以对于绝大多数输入数据达到O(nlogn)的期望时间复杂度。
方法3 三数取中
引入的原因:虽然随机选取基准时,减少出现不好分割的几率,但是还是最坏情况下还是O(n^2),要缓解这种情况,就引入了三数取中选取基准。
分析:最佳的划分是将待排序的序列分成等长的子序列,最佳的状态我们可以使用序列的中间的值,也就是第N/2个数。可是,这很难算出来,并且会明显减慢快速排序的速度。这样的中值的估计可以通过随机选取三个元素并用它们的中值作为基准元而得到。事实上,随机性并没有多大的帮助,因此一般的做法是使用左端、右端和中心位置上的三个元素的中值作为基准元。显然使用三数中值分割法消除了预排序输入的不好情形,并且减少快排大约5%的比较次数
#include<stdio.h>
int qsort[1000001];
int N;
int main()
{
void quickSort(int left, int right);
scanf("%d",&N);
int i = 1;
while (i<=N)
{
scanf("%d",&qsort[i]);
i++;
}
quickSort(1, N);
i = 1;
while (i <= N)
{
printf("%d ", qsort[i]);
i++;
}
system("pause");
return 0;
}
//以第一个为基准数会遇到大数据的时候可能会超时
void quickSort(int left,int right)
{
int i, j;
int temp;
//定位左右
i = left;
j = right;
//以中间的为基准值,如果以第一个会遇上大数据会超时
temp = qsort[(left+right)/2];
while (i <= j)
{
while (temp < qsort[j])
{
j--;
}
while (temp > qsort[i])
{
i++;
}
if (i <= j)
{
int t=qsort[i];
qsort[i] = qsort[j];
qsort[j] = t;
//此时的i,j已经处理过
i++;
j--;
}
}
if (j > left)
{
quickSort(left, j);
}
if (right > i)
{
quickSort(i, right);
}
}