以下是通俗易懂的快速排序!摘自《啊哈!算法》,我将书中的C语言写成了Java语言。因为我觉得它真的很容易明白,所以我并将把他记录了下来,并分享给大家!


假设我们现在对“6 1 2 7 9 3 4 5 1 0 8”这10个数进行排序。首先在这个序列中随便找一个数作为基准数(不要被这个名词吓到了,这就是一个用来参照的数,待会儿你就知道它用来做啥了)。为了方便,就让第一个数6作为基准数吧。接下来,需要将这个序列中所有比基准数大的数放在6的右边,比基准数小的数放在6的左边,类似下面这种排列。

3 1 2 5 4 6 9 7 1 0 8

在初始状态下,数字6在序列的第1位。我们的目标是将6挪到序列中间的某个位置,假设这个位置是k。现在就需要寻找这个k,并且以第k位为分界点,左边的数都小于等于6,右边的数都大于等于6。想一想,你有办法可以做到这点吗?

给你一个提示吧。请回忆一下冒泡排序是如何通过“交换”一步步让每个数归位的。此
时你也可以通过“交换”的方法来达到目的。冒泡排序很浪费时间,每次都只能对相邻的两个数进行比较,这显然太不合理了。于是“快速排序”就要比冒泡排序要更快。


分析如下:

方法其实很简单:分别从初始序列“6 1 2 7 9 3 4 5 1 0 8”两端开始“探测”。先从右往左找一个小于6的数,再从左往右找一个大于6的数,然后交换它们。这里可以用两个变量i和j,分别指向序列最左边和最右边。我们为这两个变量起个好听的名字“哨兵i”和“哨兵j”。刚开始的时候让哨兵i指向序列的最左边(即i=1),指向数字6。让哨兵j指向序列的最右边(即j=10),指向数字8。

首先哨兵j开始出动。因为此处设置的基准数是最左边的数,所以需要让哨兵j先出动,这一点非常重要(自己想一想为什么)。哨兵j一步一步地向左挪动(即j–),直到找到个小于6的数停下来。接下来哨兵i再一步一步向右挪动(即i++),直到找到一个大于6的数停下来。最后哨兵j停在了数字5面前,哨兵i停在了数字7面前。

现在交换哨兵 i 和哨兵 j 所指向的元素的值。交换之后的序列如下。
6 1 2 5 9 3 4 7 10 8

到此,第一次交换结束。接下来哨兵 j 继续向左挪动(再次友情提醒,每次必须是哨兵
j 先出发)。他发现了 4(比基准数 6 要小,满足要求)之后停了下来。哨兵 i 也继续向右挪
动,他发现了 9(比基准数 6 要大,满足要求)之后停了下来。此时再次进行交换,交换之
后的序列如下。
3 1 2 5 4 6 9 7 10 8


到此第一轮“探测”真正结束。此时以基准数 6 为分界点,6 左边的数都小于等于 6,6
右边的数都大于等于 6。回顾一下刚才的过程,其实哨兵 j 的使命就是要找小于基准数的数,
而哨兵 i 的使命就是要找大于基准数的数,直到 i 和 j 碰头为止。

OK,解释完毕。现在基准数 6 已经归位,它正好处在序列的第 6 位。此时我们已经将
原来的序列,以 6 为分界点拆分成了两个序列,左边的序列是“3 1 2 5 4”,右边的序列是“9 7 10 8”。接下来还需要分别处理这两个序列,因为 6 左边和右边的序列目前都还是很混
乱的。不过不要紧,我们已经掌握了方法,接下来只要模拟刚才的方法分别处理 6 左边和右
边的序列即可。现在先来处理 6 左边的序列吧。左边的序列是“3 1 2 5 4”。也是照猫画虎同样的做法!调整完毕之后的序列的顺序应该是:
2 1 3 5 4

OK,现在 3 已经归位。接下来需要处理 3 左边的序列“2 1”和右边的序列“5 4”。对
序列“2 1”以 2 为基准数进行调整,处理完毕之后的序列为“1 2”,到此 2 已经归位。序列
“1”只有一个数,也不需要进行任何处理。至此我们对序列“2 1”已全部处理完毕,得到
的序列是“1 2”。序列“5 4”的处理也仿照此方法,最后得到的序列如下。
1 2 3 4 5 6 9 7 10 8

对于序列“9 7 10 8”也模拟刚才的过程,直到不可拆分出新的子序列为止。最终将会
得到这样的序列:
1 2 3 4 5 6 7 8 9 10

到此,排序完全结束。细心的同学可能已经发现,快速排序的每一轮处理其实就是将这
一轮的基准数归位,直到所有的数都归位为止,排序就结束了。下面上个霸气的图来描述下
整个算法的处理过程。

快速排序之所以比较快,是因为相比冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样只能在相邻的数之间进行交换,交换的距离就大得多了。因此总的比较和交换次数就少了,速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。因此快速排序的最差时间复杂度和冒泡排序是一样的,都是 O(N2),它的平均时间复杂度为 O (NlogN)。其实快速排序是基于一种叫做“二分”的思想。我们后面还会遇到“二分”思想,到时候再聊。先上代码,如下。

/**
* @author Ziph
* @date 2020年3月1日
* @Email mylifes1110@163.com
*
* 快速排序
*/
public class TestQuickSort {public static void main(String[] args) {//创建一个数组并给每个数组元素赋值int[] a = new int[] {19, 23, 5, 7, 16, 0, 10};//调用快排方法quickSort(a, 0, a.length - 1);//打印输出排好序的数组元素for (int i = 0; i < a.length; i++) {System.out.print(a[i] + " ");}}public static void quickSort(int[] a,int left,int right){//分别创建i哨兵、j哨兵、temp存储基准数的临时变量、t交换的临时变量int i,j,temp,t;//终止递归,终止排序的条件(此时已经是排好的顺序)if (left > right) {return;}//分别用i、j存储两个哨兵i = left;j = right;//temp存储的就是基准数temp = a[left];//跳出while循环之后,因为循环的条件是i<j,所以,跳出循环时,i和j是相等的while (i < j) {//哨兵j从右往左找while (temp <= a[j] && i < j) {j--;}//哨兵i从左往右找while (temp >= a[i] && i < j) {i++;}//交换两个数在数组中的位置if (i < j) {//当哨兵i和哨兵j没有相遇时t = a[j];a[j] = a[i];a[i] = t;}}//最终基准数归位a[left] = a[i];a[i] = temp;quickSort(a, left, j - 1);//继续处理左边的,这里是递归的过程quickSort(a, j + 1, right);//继续处理右边的,这里是递归的过程}
}

执行结果:

0 5 7 10 16 19 23

Java快速排序(简单版)相关推荐

  1. 整体复盘----java实现简单版的坦克对战

    一.预备知识 1.java绘图机制 2.多线程基础 二.实现过程 Tank类(抽象出坦克的共有属性比如横纵坐标.方向.子弹对象及子弹数量,构造器只有横纵坐标并提供相应的getter和setter方法: ...

  2. JAVA小游戏之打字母(简单版和升级版)

    简单版: 规则:没有时间限制,点对加十分,出界抠十分 import javax.swing.*; import java.awt.*;/*** 原理:* 1.生成字母 (绘制字母)* 2. 生成坐标系 ...

  3. java实现简单扫码登录功能(模仿微信网页版扫码)

    java实现简单扫码登录功能 模仿微信pc网页版扫码登录 使用js代码生成qrcode二维码减轻服务器压力 js循环请求服务端,判断是否qrcode被扫 二维码超时失效功能 二维码被扫成功登录,服务端 ...

  4. java飞鸽传书_java简单版飞鸽传书

    [实例简介] 使用java实现的简单版飞鸽传书,可以单聊.群聊.发送文件,使用UPD获取在线用户及聊天,使用TCP发送文件.代码比较简洁,界面工整,学习使用. [实例截图] [核心代码] simple ...

  5. java简单版扫雷实现

    java简单版扫雷实现 实现原理 直接贴代码 成果展示 实现原理 扫雷实现第一步就是生成棋盘,第二步就要生成每个棋子,定义棋子属性是否是地雷,第三部就是给不是地雷的棋子赋值(附近多少地雷). 直接贴代 ...

  6. java随机yujie_植物大战僵尸简单版教程java版

    作者:叁念 1.闲来无事,做了个简单版的植物大战僵尸,不多说直接看效果图: 2.程序的项目结构如下: 3.先上素材 图片素材 链接:https://pan.baidu.com/s/1dGqqIkx 密 ...

  7. java课设 简单九宫格_[Java教程]简易版九宫格相加数值相等

    [Java教程]简易版九宫格相加数值相等 0 2016-02-24 00:00:10 九宫格的样子以及游戏想大家接触过,想当年也是玩了好多九宫格游戏,其中最经典的就是1-9这九个数字填进格子,横竖向. ...

  8. 《仙剑奇侠传柔情版》Java的简单实现(二)

    基于<仙剑奇侠传柔情版>Java的简单实现(二) 2018-12-02 by louis 需要上次的GameFrame.class中窗口框架承载:https://www.cnblogs.c ...

  9. 基于《仙剑奇侠传柔情版》利用Java的简单实现(一)

    基于<仙剑奇侠传柔情版>利用Java的简单实现(一) 2018-12-01 23:55:36   by Louis  一,新建一个类GameFrame.class,具体代码如下: pack ...

  10. 用JAVA写一个简单版的记事本

    下面的代码是一个简单版的记事本.如果需要更多的功能,可以自己去摸索一下更多的功能. import java.awt.FlowLayout; import java.awt.event.ActionEv ...

最新文章

  1. Nature | 复旦大学把衣服变成了显示器,能聊天能导航,水洗弯折都不怕
  2. very_confusing
  3. iOS 模型数组去重复
  4. 程序员,你想不想进大厂?
  5. 减少运维工作量,如何通过 ROS 轻松实现资源编排新方式
  6. cocos2d-x win8下的环境配置和建立项目
  7. 每日程序C语言19-求阶乘的前20项和
  8. ejb 2.1 jboss_JBoss AS 8中的Java EE 7和EJB 3.2支持
  9. 回顾计算机产业发展的4个阶段:美国企业统治全球市场了吗?
  10. mysql存储过程含义,MySQL存储过程定义中的特性(characteristic)的含义
  11. python输出99乘法表_如何用python输出99乘法表
  12. day17 Python 反射获取内容和修改内容
  13. 判断一个字符串(str)是否以指定的字符串(target)结尾。 如果是,返回true;如果不是,返回false。...
  14. webpack的安装和执行
  15. linux 删除用户 currently logged in,userdel删除用户失败提示:userdel: user * is currently logged in 解决方法...
  16. html只能用鼠标进行各种操作,鼠标的基本操作有哪些?
  17. 输入一串数字统计0到9每个数字的个数
  18. html5诊断报告,放射科诊断报告模板.docx
  19. 安卓网页自动填充_敏感插件限时显示提供!自动填写网盘提取码,且用且珍惜...
  20. 微信网页授权校验文件

热门文章

  1. 如何使用 notepad++ 对两个文件比较差异
  2. c语言memset函数用法,C语言memset函数使用方法详解
  3. C#连接Access2013
  4. 计算机组装与维护三—— 认识BIOS与CMOS 、设置常用BIOS、清除CMOS参数
  5. Visual Studio 2019字体颜色配置
  6. 【图文教程】用“iz3d”软件将您的游戏打造为红蓝3D游戏。
  7. ie 无人操作自动关闭_IE浏览器自动关闭的原因及解决办法
  8. 新安装的交换机连接路由器使用,详细配置方法
  9. FLIR推出首款非制冷型甲烷气体检测热像仪
  10. USB-RS232转换器芯片的特点与优势