基本思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行递归排序,以达到整个序列有序的目的。即任取待排记录的某一个记录(如第一个记录)作为基准,按照该记录的关键字大小将整个序列划分成左右两个子序列:
左侧的子序列中的所有记录的关键字都小于或等于基准记录的关键字
右侧的子序列中的所有记录的关键字都大于或等于基准记录的关键字
基准记录排在这两个子序列中间
然后对两个子序列重复上述方法,直到所有的记录都排在了相应位置上为止。
#include <stdio.h> void swap(int array[], int i, int j) { int temp; temp = array[i]; array[i] = array[j]; array[j] = temp; } /** * 划分子序列, 返回枢轴元素存放的位置 **/ int partition(int array[], int low, int high) { int pivotvalue = array[low]; //将第一个元素作为枢轴 while( low < high ) { //查找比枢轴元素小的元素交换到低端 while( (low < high) && (array[high] >= pivotvalue) ) high--; swap(array, low, high); //查找比枢轴元素大的元素交换到高端 while( (low < high) && (array[low] <= pivotvalue) ) low++; swap(array, low, high); } //退出while循环的条件是low == high,他们指向了枢轴元素应该在的位置 return low; } void QSort(int array[], int low, int high) { if(low < high) { int pivot = partition(array, low, high); QSort(array, low, pivot-1); //对低于枢轴元素的子序列递归排序 QSort(array, pivot+1, high); //对高于枢轴元素的子序列递归排序 } } void QuickSort(int array[], int len) { QSort(array, 0, len-1); } int main() { int i = 0; int array[] = {3, 1,5, 7, 9, 4, 6, 3, 2, 1}; int len = sizeof(array) / sizeof(array[0]); QuickSort(array, len); for(i=0; i < len; i++) { printf("%d ", array[i]); } printf("\n"); return 0; }
对于快速排序的时间复杂度的平均情况是O(n*logn),但是最坏情况下,即待排序列为正序或者逆序时,时间复杂度还是O(n*n)。 是一种不稳定的排序方法。
对于快速排序的几种优化:
1、对于枢轴元素的选取,如果选取的是序列的最大值或最小值,那么整个序列没有实质性的变化。所以提出了随机选取枢轴法和三数取中法。随机选取枢轴也有可能是最大值或最小值,不太好。 三数取中法则是随机选取序列的三个元素,对它们排序,取中间的元素作为枢轴,这样既不是最大值,也不是最小值。
2、优化不必要的交换
int partition(int array[], int low, int high) { int pivotvalue = array[low]; //将第一个元素作为枢轴 while( low < high ) { while( (low < high) && (array[high] >= pivotvalue) ) high--; //swap(array, low, high); array[low] = array[high]; while( (low < high) && (array[low] <= pivotvalue) ) low++; //swap(array, low, high); array[high] = array[low]; } //退出while循环的条件是low == high,他们指向了枢轴元素应该在的位置 array[low] = pivotvalue; return low; }
3、优化递归操作
当序列的记录非常多时,再加上序列的划分极端不平衡,递归操作的深度将趋近与n,有可能导致栈溢出。
void QSort(int array[], int low, int high) { if(low < high) { int pivot = partition(array, low, high); QSort(array, low, pivot-1); //对低于枢轴元素的子序列递归排序 //QSort(array, pivot+1, high); //对高于枢轴元素的子序列递归排序 low = pivot+1; //用迭代取代递归 } }