快速排序
如其名,快速排序(quicksort)是在实践中最快的已知排序算法,平均运行时间是O(NlogN),最坏情况下为O(N^2)。像归并排序一样,它也是一种分治的递归算法。
将数组S排序的基本算法由如下4步组成:
1. 若S中元素个数是0或1,则返回。
2. 取S中任一元素v,称之为枢纽元(pivot)。最好的选择是取S的中值。
3. 将S中除去枢纽元其余元素分成两个子集,一个子集S1中的所有元素都比枢纽元小,另一个子集S2中元素都比枢纽元大。
4. 分别调用quicksort(S1),quicksort(S2)。
《C程序设计语言》一书中将这个算法作为讲解递归的例子,很经典,代码如下:
#include <stdio.h> void swap(int v[], int i, int j) { int temp; temp = v[i]; v[i] = v[j]; v[j] = temp; } void qsort(int v[], int left, int right) { int i, last; if (left >= right) /* 0 or 1 element, return */ return; swap(v, left, (left + right) / 2); /* move pivot(the middle element) to the first */ last = left; for (i = left + 1; i <= right; i++) /* divide v into two subsets */ { if (v[i] > v[left]) swap(v, ++last, i); } swap(v, left, last); /* swap pivot to the [last] position */ qsort(v, left, last - 1); qsort(v, last + 1, right); } int main() { int i; int array[10] = {7, 0, 3, 8, 4, 2, 9, 1, 5, 6}; qsort(array, 0, 9); for (i = 0; i < 10; i++) printf("%d ", array[i]); putchar('\n'); return (0); }
这个例子中分割成两个子集时有点技巧:1.将枢纽元与第一个元素交换,使得枢纽元离开要被分割的数据段;2.将所有大元素移至左边;3.将枢纽元(第1个)与最后一个大于枢纽元的元素交换。
对于很小的数组(N<20),快速排序还不如插入排序,因为它是递归的(会用到许多不必要的栈)。