快速排序图解

故事开始了

假设有这样一个场景,有个小学生给了你10000个数字,要你在一天之内把这些数字排好序,然后交给他.身为一个程序猿,你想到了排序算法,进而又想到了快速排序.那么快速排序是怎么实现的呢?

既然10000个数字能排序,那么6个数字也能排序,只要6个数字时,运行结果是准确的,那么这个排序算法就能通用任意个数字的排序.假设我们有这么6个数字:

3 7 2 1 4 6 .首先,快速排序要找个基准点,一般是开头的数字,在我们这个例子中是3,然后想办法把3放到数列的中间位置,使得左边的数字比3小,右边的数字比3大,然后再递归3左右两边的数组,继续使用快速排序,最后就能全局排序.所以要搞清楚,有什么办法可以做到我们要的效果.一个可行的方法是这样的:在数组的头部和尾部各放置一个指针,然后让尾巴和3进行比较,如果大于等于3,那么就往左移动,如果碰到了比3大的数,那么就停下来.另外,如果碰到了左边的指针,也要停下来,这说明我们要的效果已经达到了.说这么多,可能还不够直观,我们用图的方式来模拟这个过程.

起初,整个指针的位置是这样的:

指针继续向左移动,6比3大,4也比3大,直到遇到了1,比3小,这个时候右边的指针就停下来,并且在移动过程中并未碰到左边的指针.现在指针的位置是这样的:

同理,左边的指针如果小于等于3,也要向右移动,直到遇到比3大的数,或者遇到了右指针也要停下来.3等于3,向右移动,7大于3,停下来,现在指针的位置是这样的:

此时,我们把两个指针所指的数字交换一下,为什么要交换呢?因为我们要使得左边的数比3小,右边的数比3大,然后就形成了下面这张图:

此时,两个指针还未碰到,但是我们能看到的是:右指针右边的数据全部比3大,左指针左边的数字全部比3小.这是一个很直观的现象.

接着,我们继续移动右指针,这里的7还要和3再比较一次,当然肯定是比3大,所以一定会左移.然后2比3小,右指针又停下来了:

然后左指针用1和3比,肯定要向右移动,然后移动过去时,发现碰到了右指针:

它们撞到一起去了,这个时候我们已经达到了我们的目的,这就是左右指针停下来的一个标志,我们把开头的3和此时这个位置上的2进行一个交换,那么就变成了:

卧槽!我们达到我们的终极目的:使得3左边的数字比3小,右边的数字比3大.

接下来的故事是,保持3这个位置不动,将左边的2,1当成一个数组,右边的7,4,6当成一个数组,然后再重新对每个数组搞两个指针进行移动,切记:撞到了就是成功了 .那么我们可以使用递归的方式来做剩余的事情.如果数组只剩下一个元素,那么一定要结束递归,此时的结束条件是i>=j.下面将展示快速排序的代码,也就是模拟我们现在的整个过程.

快速排序代码

scss 复制代码
   public static void quickSort(int [] nums,int i,int j) {
        if(i>=j){
            return;
        }
        int start = i;
        int end = j;
        int basic = nums[i];
        while(i < j) {
            while(i<j && nums[j] >= basic) {
                j--;
            }
            while(i< j && nums[i] <= basic) {
                i++;
            }
            if(i<j) {
                ArrayUtil.swap(nums, i, j);
            }
        }
        ArrayUtil.swap(nums,i,start);
        quickSort(nums,start,i-1);
        quickSort(nums,i+1,end);
    }

首先代码的开始是判断是不是要结束递归,紧接着,搞出两个指针,开始和开头位置的数字进行比较.代码里面始终要判断i<j,因为撞到了就是成功了,无需再进行下去,另外再没撞到之前,如果双方都停下来一次之后,要交换一下所指的数字,这是为了确保右边的数字比开头的数字大,左边的数字比开头的数字小.

然后,如果i和j相遇,那么一次完整的快速排序就结束了,在遇到的地方和开头的数字进行一次交换,接着再进行左右两个数组的排序,如此递归下去,直到排完.

故事的最后

你轻轻松松的排完了10000个数字,写下代码的过程只用了59秒,接着你拿起了桌上那瓶95年的可乐喝了一口,顺手掏出了手机,开始刷起了你养了多年的B站号,进入了传说中的工作休息区.

相关推荐
Javatutouhouduan17 分钟前
如何系统全面地自学Java语言?
java·后端·程序员·编程·架构师·自学·java八股文
后端转全栈_小伵26 分钟前
MySQL外键类型与应用场景总结:优缺点一目了然
数据库·后端·sql·mysql·学习方法
编码浪子1 小时前
Springboot高并发乐观锁
后端·restful
Mr.朱鹏2 小时前
操作002:HelloWorld
java·后端·spring·rabbitmq·maven·intellij-idea·java-rabbitmq
编程洪同学3 小时前
Spring Boot 中实现自定义注解记录接口日志功能
android·java·spring boot·后端
GraduationDesign4 小时前
基于SpringBoot的蜗牛兼职网的设计与实现
java·spring boot·后端
颜淡慕潇4 小时前
【K8S问题系列 | 20 】K8S如何删除异常对象(Pod、Namespace、PV、PVC)
后端·云原生·容器·kubernetes
customer084 小时前
【开源免费】基于SpringBoot+Vue.JS安康旅游网站(JAVA毕业设计)
java·vue.js·spring boot·后端·kafka·开源·旅游
搬码后生仔5 小时前
将 ASP.NET Core 应用程序的日志保存到 D 盘的文件中 (如 Serilog)
后端·asp.net
Suwg2095 小时前
《手写Mybatis渐进式源码实践》实践笔记(第七章 SQL执行器的创建和使用)
java·数据库·笔记·后端·sql·mybatis·模板方法模式