快速排序

快速排序被列为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 7
void 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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值