快速排序(QuickSort)学习记录&个人理解

本文详细阐述了快速排序算法的基本思想、代码实现及其优化策略,包括合理选择枢轴、优化交换操作、处理小数组时的排序方案以及递归操作的尾递归优化,旨在提升算法性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。

**以下代码假设L->r[0]作为哨兵,要排序的数列从r[1]开始**

基本算法代码

void QuickSort(SqList *L)
{
    Qsort(L,1,L->length);//对顺序表L进行排序
}

/*
对顺序表L中的子序列L->r[low...high]进行快速排序
参数解释:
        low:当前待排序列的序列最小下标
        high:当前待排序列的序列最大下标
        pivot:称为枢轴,在枢轴左边的值都比它小,在枢轴右边的值都比它大  
*/
void Qsort(SqList *L,int low,int high)
{
    int pivot;
    if(low < high)
    {
        pivot = Partition(L,low,high);

        Qsort(L,low,pivot-1);
        Qsort(L,pivot+1,high);
    }
}
/*
    交换顺序表L中的子表记录,使枢轴记录到位,并返回枢轴所在位置
    参数解释:
        pivotkey:枢轴的值,用于与待排记录比较
*/
int Patition(SqList *L,int low,int high)
{
    int pivotkey;

    pivotkey = L->r[low];//用子表的第一个记录作为枢轴记录
    while(low < high)
    {

        while(low < high && pivotkey <= L->r[high])
            high--;
        swap(L,low,high);

        while(low < high && pivotkey >= L->r[low])
            low++;
        swap(L,low,high);

    }
    return low;
}

可以看出,整个排序最重要的是Partition函数,即如何找到一个枢轴。
Partition函数其实就是将选取的pivotkey不断交换,将比它小的换到它的左边,比它大的放到右边,而pivot也在不断地改变自己的位置,知道满足这个要求为止。

思考:基本算法的代码还可以优化吗?

1.优化选取枢轴

   最理想的情况是,子表第一个记录永远是当前序列中的中间数,这样**如何合理地获得中间数**作为枢轴是提升性能的一个关键。
 一般的方法有**随机选取枢轴法**(生产随机数需要额外开销,浪费资源,而且还不一定是中间数,不可取)
 为了获得一个序列的中间数,我们可以采用**三数取中**的方法:
 即选取三个关键字进行排序,将3个关键字的中间数作为枢轴,一般取左端,右端和中间三个数,优化代码如下(在基本算法Partition方法的第三行加入如下代码):
    int m = low + (high - low)/2;//获得数组中间位置的下标
    if(L->r[low] > L->r[high])
        swap(L,low,high);//交换左端与右端的数据,保证左端较小
    if(L->r[m] > L->r[high])
        swap(L,low,high);//交换中间与右端数据,保证中间较小
    if(L->r[m] > L->[low])
        swap(L,low,high);
    /*此时L->r[low]已是整个序列左中右3个关键字的中间值*/

2.优化不必要的交换

由于swap方法需要声明一个临时变量且进行3次赋值,如果可以优化swap方法或者不使用swap方法,效率会更高。
通过观察发现,我们可以用一个哨兵来存储当前pivotkey,在high(low)游标移动后,直接进行替换操作
L->r[low] = L->r[high](L->r[high] = L->r[low])
最后 在low和high游标汇合的时候L->r[low] = L->r[0]
这样可以减少交换从而提高算法性能

3.优化小数组时的排序方案
当数组长度较小时,使用直接插入排序会比快拍性能高
数组长度阀值(7或50)

4.优化递归操作
实施尾递归优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值