java快速排序,深入浅出,不懂的来看这里~

前段时间,我以前大学的一个学长去面试的时候,就问到了快速排序,并要求手写出来,那么,如果问到你,能不能在手纸上,呸!。。。在纸上写出来呢?

java的快速排序是面试经常要考到的哟!本文章接下来会深入浅出让大家能够了解快速排序,并能够知道快速排序的原理哦~

1,什么是快速排序?

让我们先来了解一下什么是快速排序,快速排序也叫快排,是冒泡排序的升级版,其效率要远高于冒泡排序,是一种高级的排序方式
它采用分而治之的思想,来完成排序

2,快速排序的思想

这里先了解一下即可,后面会有图解
采用分而治之的思想

1. 随便选一个数作为中轴点,将数组以中轴点作为分界线,分为左右两部分,
2.  以从小到大的排序为例,左边部分的值都要小于右边的值
   (换而言之,就是左边部分都小于中轴点的值,右边部分都大于中轴点的值)
3. 左右两部分能够再分就继续分(待分的部分长度大于1),
   重复这个操作,直到数组不可再分为止,到这里我们的排序就已然完成

让我们看一下图解:
从上往下看,从左往右看
所有算法都是思想最重要,如果你看懂了思想的话,就请继续往下看,else-》请就着图解,仔细阅读思想,把思想看懂再看代码!!!

3,代码实现

public static void main(String[] args) {
        int[] arr={14,4,1,5,2,6,17};
        quickSort(arr);//测试快速排序
        System.out.println("Arrays.toString(arr) = " + Arrays.toString(arr));
    }

    /*快速排序*/
    private static void quickSort(int[] arr) {
        group(arr,0,arr.length-1);
    }

    /**
     * 快速排序的分组方法【就是通过中轴值(随意从待排序的数组中选一个值,
     * 为了方便,我直接选左边第一个)
     * @param arr 数组
     * @param lo  (low的简写)待排序部分最左边的值的下标
     * @param hi  (high的简写)待排序部分最右边的值的下标
     */
    private static void group(int[] arr, int lo, int hi) {
        //安全验证
        if(lo>=hi)
            return;

        //通过快速排序的核心方法获取中心点
        //【虽然我们这里是选待排序数组的左边第一个(即lo),
        //但是经过核心方法之后,中轴的位置已然改变,
        //所以不能直接用lo这个下标】
        int pivot = core(arr,lo,hi);

        //这里递归调用分组的方法【表示分组完成后继续分组】
        group(arr,lo,pivot-1);
        group(arr,pivot+1,hi);
    }

    /**
     * 快速排序的核心方法【实际上就是双指针算法
     * (不要看到算法就觉得困难哦,
     * 这个十分简单!哈哈~下面会为大家注释好,放心观看)】
     * @param arr  数组【这个数组实际用到的部分就是lo-hi的部分】
     * @param lo  (low的简写)待排序部分最左边的值的下标
     * @param hi  (high的简写)待排序部分最右边的值的下标
     * @return 分好左右两边后,中轴所在位置的下标
     */
    private static int core(int[] arr, int lo, int hi) {
        int pivot=lo;//中轴的位置,我们选左边第一个

        //定义左右指针(就是int类型的变量)
        int left=lo,right=hi;

        //指针指向待排序数组的左右两端,从右边开始遍历,找到一个比中轴小的,
        //然后从左边找遍历到一个大的,交换两者的位置
        while(left<right){
            while(left<right&&arr[right]>=arr[pivot]) right--;
            while(left<right&&arr[left]<=arr[pivot]) left++;

            //交换左右值的位置
            change(arr, left, right);
        }

        //经过循环后,左右指针已经重合在一起,我们交换中轴与左指针元素的位置
        //【为什么重合在一起了?请看第一个while的条件】
        change(arr,pivot,left);//这里还可以稍微简化,不过效果差不多
        
        return left;
        //因为中轴值和左指针元素交换了位置,所以返回左指针元素
    }

    /**
     * 交换两个数在数组中的位置
     * @param arr
     * @param left
     * @param right
     */
    private static void change(int[] arr, int left, int right) {
        int temp=arr[left];
        arr[left]=arr[right];
        arr[right]=temp;
    }

说明:不要被长篇幅吓到哦,基本上都是注释,代码很少

4,时间复杂度和稳定性

平均时间复杂度:O(nlogn)
最差时间复杂度:O(n^2)
稳定性:不稳定的排序【排完序后两个相等的元素没有交换位置就是稳定的排序】

时间复杂度是衡量算法效率的东西,如果想要清楚地了解,欢迎在评论区留言,那么我下期就会出一期关于时间复杂度的专栏讲解

5,与冒泡排序花费的时间比较

排序一百万条数据,
快速排序花费时间:170ms
冒泡排序花费时间:等了好几分钟都不出结果
申明:不同的设备,花费的时间可能有些不同哦!
结论:完败冒泡

看在我这么用心的份上,动动你的小手帮我点个赞吧,这会让作者更加有动力为你们写文章哦,谢谢啦~

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值