快速排序

来源:互联网 发布:文泰2009端口设置 编辑:程序博客网 时间:2024/06/05 14:44

快速排序被列为20世纪十大算法之一。
基本思想是:选取一个枢轴,通过一趟排序将待排记录分割成独立的俩部分,其中一部分记录比枢轴小,另外一部分记录比枢轴大;然后再继续对分割好的的字序列进行上述排序。

实现代码

void swap(int *a, int low, int high){    int temp = a[low];    a[low] = a[high];    a[high] = temp;}// 交换a中字表的记录,是枢轴记录到位,并返回其位置// 此时枢轴之前(后)的记录均不大(小)于它int Partition(int *a, int low, int high){    int pivotKey = a[low];                                 // 用字表的第一个记录作枢轴记录    while (low < high)                                     // 从表的俩端交替向中间扫描    {        while (low < high && pivotKey <= a[high])        {            high--;        }        swap(a, low, high);                                // 将比枢轴记录小的记录交换到低端        while (low < high && pivotKey >= a[low])        {            low++;        }        swap(a, low, high);                                // 将比枢轴记录大的记录交换到高端    }    return low;                                            // 返回枢轴的位置}// 对顺序表a的子序列作快速排序void QSort(int *a, int low, int high){    int pivot;    if (low < high)    {        pivot = Partition(a, low, high);   // 将a一分为二、返回枢轴位置        QSort(a, low, pivot - 1);          // 对低字表递归排序        QSort(a, pivot + 1, high);         // 对高子表递归排序    }}// 对序列表a进行快速排序void QuickSort(int *a, int len){    QSort(a, 0, len - 1);}

快速排序优化

  1. 优化选取枢轴
    直接选取表的第一个记录作为枢轴,如果第一个记录正好是整个表的中间数是最理想的,但实际情况是第一个记录往往偏大或偏小,甚至极端情况是最大或最小,此时第一个记录作为枢轴显然是不合适的,故一般采用“三数取中”法——即选取头尾和中间三个数,也可速记选取,取中间值作为枢轴。或“九数取中”法,即选取三组数,算出分别算出中间值,再在这三个中间值中选取中间值作为枢轴。
int mid = low + (high - low) / 2;if (a[low] > a[high]){    swap(a, low, high);}if (a[mid] > a[high]){    swap(a, mid, high);}if (a[low] < a[mid]){    swap(a, low, mid);}int pivotKey = a[low];                                 // 用字表的第一个记录作枢轴记录
  1. 优化小数组时的排序方案
    当数组较小时,直接采用直接插入排序,性能更好
    对QSort函数进行改进即可。
    high - low 大于某个常数,有资料说7合适,也有说50合适,实际情况可自行调整。
#define MAX_LEN_INSERT_SORT 7void QSort(int *a, int low, int high){    int pivot;    if ((high - low) > MAX_LEN_INSERT_SORT)    {        pivot = Partition(a, low, high);   // 将a一分为二、返回枢轴位置        QSort(a, low, pivot - 1);          // 对低字表递归排序        QSort(a, pivot + 1, high);         // 对高子表递归排序    }    else    {        InsertSort(int *a, int len);    }}
  1. 优化递归操作
void QSort(int *a, int low, int high){    int pivot;    if ((high - low) > MAX_LEN_INSERT_SORT)    {        while (low < high)        {            pivot = Partition(a, low, high);   // 将a一分为二、返回枢轴位置            QSort(a, low, pivot - 1);          // 对低字表递归排序            low = pivot + 1;                   // 尾递归优化法        }    }    else    {        InsertSort(int *a, int len);    }}