快速排序就是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交汇。