快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。
算法步骤:
1 从数列中挑出一个元素,称为 “基准”(pivot),
2 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
3 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
根据以上排序原理,拿快速排序练练手,基本思想就是选取一较为中间大小的值,分别从两边循环跟此值对比,若小于其,
则换至该值前面,若大于其,则换至该值后面,直到low == high 为止,则说明排序结束。 以简单的int数组为待排序序列:
/*
* QuickSort
*
* 2015.11.21
* By Snow Yong
*/
#define MINIMUMSIZE 7
#define A_LENGTH 10
#include <stdio.h>
int Swap(int *a, int i, int j);
int QuickSort(int *a);
int Qsort(int *a, int low, int high);
int Partition(int *a, int low, int high);
int PickMiddle(int *a, int low, int high);
int InsertSort(int *a);
//元素交换函数
int Swap(int *a, int i, int j)
{
int temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
//快速排序主函数
int QuickSort(int *a)
{
Qsort(a, 0, A_LENGTH-1);
}
//快速排序处理函数
int Qsort(int *a, int low, int high)
{
int pivot;/*pivot用于存放序列选取出的枢轴值*/
/*if-else条件语句用于处理小数组处理的问题,
* 具体序列值 n 说法不一,此处定为7。若数组
* 个数较小采用简单插入排序,效率更高。
*/
if ((high - low) > MINIMUMSIZE)
{
//if (low < high)
while (low < high)
{
pivot = Partition(a, low, high);
Qsort(a, low, pivot-1);
//Qsort(a, pivot+1, high);
low = pivot + 1;
}/*用while循环优化尾递归,提高整体性能*/
}
else
{
InsertSort(a);
}/*遇到小数组(序列)改用插入排序*/
}
//求枢轴值的函数
int Partition(int *a, int low, int high)
{
int temp;
PickMiddle(a, low, high);/*此处是为平衡取得较中间值,并将此值赋予a[low]*/
temp = a[low];
while (low < high)
{
while (low < high && a[high] >= temp)/*注意事项:此处必须为 >= 而非 > ,否则可能陷入死循环*/
{
high--;
}
// Swap(a, low, high);
a[low] = a[high];/*优化不必要的交换,提高效率*/
while (low < high && a[low] <= temp)/*注意事项:此处必须为 <= 而非 < ,否则可能陷入死循环*/
{
low++;
}
// Swap(a, low, high);
a[high] = a[low];/*优化不必要的交换,提高效率*/
}
a[low] = temp;/*此时a[low]已处于中间位置,将最初的中间值temp赋回*/
return low;/*返回枢轴*/
}
//三数取中法,保证所取作为枢轴的数组值大小处于较中间的位置,存于a[low]处
int PickMiddle(int *a, int low, int high)
{
int m = (low + high) / 2;
if (a[low] > a[high])
{
Swap(a, low, high);
}
if (a[m] > a[high])
{
Swap(a, m, high);
}
if (a[low] > a[m])
{
Swap(a, low, m);
}
}
//插入排序,用于处理快速排序中的小数组(序列)问题
int InsertSort(int *a)
{
int i, j, temp;
for (i = 1; i < A_LENGTH; i++)
{
if (a[i] < a[i-1])
{
temp = a[i];
for (j = i - 1;
a[j] > temp && j >= 0;
j--)
{
a[j+1] = a[j];
}
a[j+1] = temp;
}
}
}
int main()
{
int i;
int a[A_LENGTH] = {50, 90, 80, 40, 30,
70, 60, 10, 20, 100};
printf("Before sorting:");
for (i = 0; i < A_LENGTH; i++)
{
printf("%d -- ", a[i]);
}
QuickSort(a);
printf("\n\nAfter sorting: ");
for (i = 0; i < A_LENGTH; i++)
{
printf("%d -- ", a[i]);
}
return 0;
}