快速排序就是C.R.A.Hoare 于 1962年提出一种划分交换排序,它采用了分治的策略,通常称其为分治法。分治法的基本意思是:将原问题分解为若干规模更小但结构与原问题相似的子问题,递归地解答这些子问题,然后将这些子问题的解组合为原问题的解。
快速排序的基本思想是:假设当前待排序的无序区为 A[low...high],利用分治描述如下:
(1)分解:在A[low...high]中任选一个记录作为基准(Piovt),以此为基准将当前无序区划分为左、右两个较小的子区间A[low...(pivotpos-1)]和A[(pivotpos+1)...high],并使左边子区间中所有记录的关键字均小于等于基准记录(pivot),右边的子区间中所有记录关键字均大于等于(pivot),而基准记录pivot则位于正确的位置上,无需参见后续的排序。
注意:划分的关键是求出基准记录所在位置pivotpos,划分的结果可以简单地表示为:A[low...(pivotpos-1)] <= A[pivotpos] <= A[(pivotpos+1)...high],其中pivot = A[pivotpos],low <= pivotpos <= high 。
(2)求解:通过递归调用快速排序对左、右子区间A[low...(pivotpos-1)] 和 A[(pivotpos+1)...high] 快速排序。
(3)组合:当“求解”步骤中的两个递归调用结束时,其左、右两个子区间已经有序,因而对快速排序而言,“组合”步骤无须做什么,可看做是空操作。
下面是实现代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//快速排序
void quick_sort(int a[], int low, int high)
{
int i = 0, j = 0;
int pivot = 0;
if(low < high)
{
pivot = a[low];
i = low;
j = high;
while(i < j)
{
while(i<j && a[j]>=pivot) //右边放大于pivot的数
{
j--;
}
if(i < j)
{
a[i++] = a[j]; //将比pivot小的数放到低端
}
while(i<j && a[i]<=pivot)
{
i++;
}
if(i < j)
{
a[j--] = a[i]; //将比pivot大的数放到高端
}
}
a[i] = pivot; //将pivot放到最终的适当的位置
quick_sort(a, low, i-1); //对左区间递归排序
quick_sort(a, i+1, high); //对右区间递归排序
}
}
int main()
{
int data[10] = {54, 38, 96, 23, 15, 72, 60, 45, 83, -12};
quick_sort(data, 0, 9);
for(int i=0; i<=9; i++)
{
printf("%d ", data[i]);
}
printf("\n");
return 0;
}
pivot的初始值为a[low]。局部变量i和j分别代表low和high的位置。按照下面的步骤进行一次交换:
(1)把比pivot小的元素移到低端(low)。
(2)把比pivot大的元素移到高端(high)。
(3)将pivot移到最终位置,此时这个位置的左边元素的值都比pivot小,而其右边元素的值都标pivot大。
(4)对左、右区间分别进行递归排序,从而把前面所进行的粗排序逐渐细化,直至最终low和high交汇。