快速排序的三种实现方式以及非递归版本

本文介绍了快速排序的基本思想,包括分治策略、选择基准值、分割序列和递归重复步骤。详细讲解了三种实现方式:填充法、交换法和双指针前移法,并提供了非递归版本的实现。最后,讨论了快速排序的时间复杂度和空间复杂度。
摘要由CSDN通过智能技术生成

一、快速排序的基本思想

快速排序利用了分治的思想,分而治之。通过一趟排序将序列分为两部分,其中一部分比较关键字小,一部分比关键字大。之后继续对这两个子序列重复此过程,直到整个序列都有序。

二、快速排序的三个步骤

  1. 选基准值:在要排序的序列中选一个几个基准值,作为划分区间的 关键字。通常选取关键字的方式对效率有很大的影响。
  2. 分割序列:按照基准值把序列分为两部分,左边的小于基准值,右边的大于基准值。
  3. 重复分割:对子序列重复上面的步骤,知道序列为空或者只有一个元素。当递归处理的所有子序列都返回时,序列有序。

三、三种实现方式

注:下面代码中所有区间都是左闭右开,[ left, right),且排序都是从大到小。且基准值默认选择序列的最后一个元素

一、版本一填充法

思路:两个指针 begng作为序列的开始 和 end 序列的结束。

将序列的最后一个元素保存起来,作为基准值。

开始划分序列:直到begin < end 不成立

begin 从左往右找比 基准值 大的元素,将该值填充到 end 的位置(end 位置上的值已经保存到 key),end-- ,因为已经划分好了一个元素。
end 从右往左找比 基准值小的元素,如将该值填充到 begin 的位置(begin 位置上的值已经保存到 end位置),begin++,已经划分好一个元素。

循环结束时,将 key 填充到 end 的位置,然后将 end 返回,作为下一次划分序列的边界。

// 版本一 填充法
int partition(vector<int> &v, int left, int right)
{
   
    int begin = left;
    int end = right - 1;
    int key = v[end];          // 选基准

    while (begin < end)
    {
   
        while (begin < end && v[begin] <= key)
            begin++;
        if (begin < end)
            v[end--] = v[begin];
        while (begin < end && v[end] >= key)
            end--;
        if (begin < end)
            v[begin++] = v[end];
    }
    v[end] = key;
    return end;
}
void QuickSort(vector<int>& v, int left, int right)
{
   
    if (left < right)
    {
   
        int boundary = partition(v, left, right);
        QuickSort(v, left, boundary);
        QuickSort(v, boundary + 1, right);
    }
}

二、版本二 交换法

和上面的版本一类似,不同之处是,这里不是填充,而是将找到的元素交换。

// horn版本
int partition(vector<int> &v, int left, int right)
{
   
    int begin = left;
    int end = right - 1;
    int key = v[end];
    
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值