快速排序根据整个文件,把控制当前排序进程的基准关键字放在正确的位置上,在快速排序总,如果把关键字 k1 放置在位置 s(i) 处,那么,当j< s(i) 时,则有 kj<=ks(i) ,而j> s(i) 时,则有 kj>=ks(i) ,因此,当把基准关键字放置在此位置上后,原来的文件被划分为两个子文件,其中的一个文件包含记录 R0 ,…, Rs(i)−1 ,而另一个文件包含记录 Rs(i)+1 ,…, Rn−1 .由于在排序后的序列中,第一个子文件中的所有记录都在 s(i) 的左边,而第二个子文件中的所有记录都在 s(i) 的右边,于是可以对这两个子文件进行独立排序。
输入文件包含10个记录,其关键字分别为(26,5,37,1,61,11,59,15,48,19),其排序过程如下:
R0 | R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 | R9 | left | right |
---|---|---|---|---|---|---|---|---|---|---|---|
[26 | 5 | 37 | 1 | 61 | 11 | 59 | 15 | 48 | 19] | 0 | 9 |
[11 | 5 | 19 | 1 | 15] | 26 | [59 | 61 | 48 | 37] | 0 | 4 |
[1 | 5] | 11 | [19 | 15] | 26 | [59 | 61 | 48 | 37] | 0 | 1 |
1 | 5 | 11 | [19 | 15] | 26 | [59 | 61 | 48 | 37] | 3 | 4 |
1 | 5 | 11 | 15 | 19 | 26 | [59 | 61 | 48 | 37] | 6 | 9 |
1 | 5 | 11 | 15 | 19 | 26 | [48 | 37] | 59 | [61] | 6 | 7 |
1 | 5 | 11 | 15 | 19 | 26 | 37 | 48 | 59 | [61] | 9 | 9 |
1 | 5 | 11 | 15 | 19 | 26 | 37 | 48 | 59 | 61 |
其中c常量,n为把基准记录放置在大小为n的正确位置所需的时间,T(n)表示排序具有n个记录的文件所需的时间,整个算法时间复杂度:
T(n)≤cn+2T(n/2)≤cn+2(cn/2+2T(n/4)≤2cn+4T(n/4)≤cnlog2n+nT(1)=O(nlog2n)
代码实现:
//交换数值
void swap(element &a,element &b,element temp)
{
temp=a;
a=b;
b=temp;
}
//快速排序
void quicksort(element list[],int left,int right)
{
int pivot,i,j;
element temp;
if(left<right)
{
//左边界,右边界
i=left;j=right+1;
//基准值
pivot=list[left].key;
//每次循环使左边的数全部小于基准值,右边的数全部大于基准值
do
{
//查找左边大于基准值的数
do
i++;
while(list[i].key<pivot);
//查找右边小于基准值的数
do
j--;
while(list[j].key>pivot);
//大于基准值的数和小于基准值的数交换
if(i<j)
{
swap(list[i],list[j],temp);
}
}while(i<j);
//放置基准值为正确的位置
swap(list[left],list[j],temp);
//排序左边
quicksort(list,left,j-1);
//排序右边
quicksort(list,j+1,right);
}
}