实践中最快的已知排序算法。
运行结果:
平均效率=O(NlogN)的递归算法。
算法的思想是,先找出数列中的一个枢纽,然后在每次递归中,把小于枢纽的元素放枢纽左边,大于枢纽的元素放数组右边,即先做到“大概有序”,再切分数组,逐步递归达到全局有序。
注意和归并排序的区别:
快速排序先调整,后递归。
归并排序先递归,后调整。
小数组(N<20)的情况下,快速排序不如插入排序好。所以,当递归多次后数组变得很小时,就应该使用插入排序作为辅助了。
代码:
#include <stdio.h>
void InserSort(int *array, unsigned int n)
{
int i, j;
int temp;
/* 排列n个数要进行n-1趟比较 */
for (i = 1; i < n; i++)
{
temp = array[i];
for (j = i-1; j >= 0 && array[j] > temp; j--)
array[j+1] = array[j];
array[j+1] = temp;
}
}
void exchange(int *a, int *b)
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
int Median(int *array, int left, int right)
{
int mid = (left+right)/2;
if (array[left] > array[right])
exchange(&array[left], &array[right]);
if (array[left] > array[mid])
exchange(&array[left], &array[mid]);
if (array[right] < array[mid])
exchange(&array[right], &array[mid]);
exchange(&array[mid], &array[right-1]);
return array[right-1];
}
void Sort(int *array, int left, int right)
{
int pivot;
int i, j;
if (left+3 <= right)
{
/* Median 的作用:
* 1.把左端元素、右端元素、枢纽元素进行排序
* 2.把枢纽和倒数第二个元素对调
* 3.返回枢纽值
*/
pivot = Median(array, left, right);
/* 注意,这里可以直接跳过通过 Median 函数排过序的三个元素 */
i = left + 1;
j = right - 2;
while (1)
{
while(array[i] < pivot)
i++;
while(array[j] > pivot)
j--;
if (i < j)
exchange(&array[i], &array[j]);
else
break;
}
/* 把枢纽还原 */
exchange(&array[i], &array[right-1]);
Sort(array, left, i-1);
Sort(array, i+1, right);
}
else
/* 这里用插入排序效率更高 */
InserSort(array+left, right-left+1);
}
void QuickSort(int *array, int N)
{
Sort(array, 0, N-1);
}
int main(void)
{
int array[] = {150,80,40,30,10,70,110,100,20,90,60,50,120,140,130};
int len = sizeof(array)/sizeof(array[0]);
int i;
QuickSort(array, len);
for (i = 0; i < len; i++)
printf("%d ", array[i]);
printf("\n");
return 0;
}
运行结果: