快排的两种写法和细节分析

快排是很经典的排序算法。
百度百科显示:它是对冒泡排序的一种改进,一般来讲会可以为四个步骤:

  1. 选择基准值
  2. 将数组分为两部分,左部分的数值都小于或等于基准值,右部分的数值都大于或等于基准值,相当于这一步就确定了一个基准值的最终位置
  3. 递归对左右两侧的数据进行同样方法的排序
  4. 如果某次递归中排序部分的长度为1,就直接返回,不用操作
    递归结束后,整个数组的排序就完成了!

在网上搜索代码的时候发现有多种写法,不考虑变体和优化,只看思想,我看到的主流的可以分为两种:
一种是上述过程的具体实现版本,首先通过partition操作得到基准值的所在位置,然后据此划分两个范围,递归执行。代码如下:参考链接

public void quickSort1(int[] nums,int l,int r){
        if(l>=r) return;
        int pivot = partition(nums,l,r);//得到基准数的位置
        quickSort1(nums,l,pivot-1);//递归执行左范围
        quickSort1(nums,pivot+1,r);/递归执行右范围
    }
    public int partition(int[] nums,int l,int r){
        int pivot = nums[l];//基准数
        while(l<r){
            while(l<r && nums[r]>=pivot) r--;//找比pivot大的数
            nums[l] = nums[r];
            while(l<r && nums[l]<=pivot) l++;//找比pivot小的数
            nums[r] = nums[l];//两次赋值,完成数值交换
        }
        nums[l] = pivot;//pivot的最终位置
        return l;
    }

另一种写法就是我之前看的某个网站上贴的模板,但现在找不到原地址了,原版是C++写的,Java就多写了一个swap操作,代码直接贴在这里:

    public static void quickSort2(int[] nums,int l,int r){
        if(l>=r) return;
        int i=l-1,j=r+1,x=nums[l];
        while(i<j){
            do{i++;}while(nums[i]<x);
            do{j--;}while(nums[j]>x);
            if(i<j){
                int tmp = nums[i];
                nums[i] = nums[j];
                nums[j] = tmp;
            }
            else break;
        }
        quickSort2(nums,l,j);
        quickSort2(nums,j+1,r);
    }

个人觉得这种写法更简单直观,但要注意的是,这种写法和前面提到的思路是不一样的,前一种相当于是分左中右的去做,但这一种就是只分左右,在对一个基准数操作完后,是无法保证该基准数到达了正确的最终位置的,但可以保证两个区间划分开来了,所以可以递归去执行两个区间。

这两种写法的区别可以在算法题数组中的第 k 大的数字 中深切体会到,这道题更适合用第一种,因为partition的过程其实就是不断缩小范围的过程,这样写就更直观,我们可以直接根据partion的结果去选择递归执行哪一侧,当然第二种写法也可以达到相同的目的,但是一定要注意两种写法细节上的区别!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值