排序-快排进阶-挖坑法+前后指针法

前言

上一章我们介绍了快排的第一版--hoare版,

今天我们来看一下进阶版:

挖坑法和前后指针法

回顾

基本思想:

  • 从待排序的数组中选取一个基准值.
    (我们把基准值记为key)

  • 再将数组分为两部分:
    1. 左子数组所有元素小于基准值
    2. 右子数组所有元素大于基准值

  • 左右子数组再选基准值重复这个过程

基准值的选择:

三数取中法,详情见上一节快速排序

挖坑法

基本思路:

  • 找到基准值,并记录下来
  • 将基准值的位置挖个坑位
  • 右边r先走,找比基准值小的
  • 找到后将这个值扔在坑中
  • 它本身变成新坑.以此类推
  • 当左边和右边相遇时
  • 将记录下来的key放在坑位

图示理解:

定义一个无序数组,并将最左边元素定义为基准值

走完单趟排序后key

左子数都小于key

右子数都大于key
说明key已经到达他的最终位置

接下来我们只需要不断递归
基准值的左右子序就可以使
整个数组有序

挖坑法代码实现

GetMidIndex三数取中参考上一节

int PartSort2(vector<int>& f, int left, int right)
{
    int midi = GetMidIndex(f, left, right);
    swap(f[left], f[midi]);
    int key = f[left];
    int hole = left;
    while (left < right)
    {
        //右找小
        while (left < right && f[right] >= key)
            right--;
        f[hole] = f[right];
        hole = right;
        //左找大
        while (left < right && f[left] <= key)
            left++;
        f[hole] = f[left];
        hole = left;
    }
    f[hole] = key;
    return hole;
}

递归调用函数:

void QuickSort(vector<int>& f, int begin, int end)
{
    if (begin >= end)
        return;
    int key = PartSort2(f, begin, end);
    QuickSort(f, begin, key - 1);
    QuickSort(f, key + 1, end);
}

前后指针法

基本思路:

  • 定义两个指针cur和prev
  • cur指向第二个元素
  • prev指向cur前面的元素
  • c找比基准值小的值
  • 找到后停下,p向后走一格
  • 再交换c和p指向的值
  • 最后c走完数组后:
  • 交换key和prev的值

图示理解:

祖传数组

与挖坑法一样:

走完单趟排序后key

左子数都小于key

右子数都大于key
说明key已经到达他的最终位置

接下来我们只需要不断递归
基准值的左右子序就可以使
整个数组有序

并且前后指针法和挖坑法

得出的左右子数组顺序不一样

说明它们的底层思想是不同的

前后指针法代码实现

GetMidIndex三数取中参考上一节

int PartSort3(vector<int>& f, int left, int right)
{
    int midi = GetMidIndex(f, left, right);
    swap(f[left], f[midi]);
    int cur = left+1;
    int prev = left;
    int keyi = left;
    while(cur<=right)
    {
        if (f[cur] < f[keyi] && ++prev != cur)
            swap(f[cur], f[prev]);
        cur++;
    }
    swap(f[keyi], f[prev]);
    keyi = prev;
    return keyi;
}

递归调用函数:

void QuickSort(vector<int>& f, int begin, int end)
{
    if (begin >= end)
        return;
    int key = PartSort3(f, begin, end);
    QuickSort(f, begin, key - 1);
    QuickSort(f, key + 1, end);
}

总结

不管是哪一个版本的快排

算法效率也就是时间复杂度都是一样的

下一期讲解最牛逼的非递归版快排!!!

  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值