让你一看就懂的快速排序算法(Java)
快速排序
你也许会被快速排序的文章弄得迷迷糊糊,其实大体上去看,快速排序就一步:找个数做基准数,把小于它的数移到它左边,把大于它的数移到它右边。这句话是核心。然后我们只需要让基准数左边的重复上面的步骤,让基准数右边的再重复上面的步骤就完了。
比如我们有一个数组:
int[] nums = {5, 2, 6, 8, 4, 7, 9, 1};
快速排序的思想就是使用递归,其实使用递归并不是多么复杂,在理解算法的思想后,只需要关注算法中重复的步骤,那就是递归的核心代码。
比如快速排序的算法思想,大体代码如下:
public void quick(int left, int right) {
/*
* 给这段代码起个名字为:基准校验
* 把小于基准数的移到左边,把大于基准数的移到右边
*/
quick(left, now); //继续处理左边的
quick(now, right); //继续处理右边的
}
经过一遍基准校验,我们就找到了该基准数在完全排序后的正确位置!
大体算法的流程图:

写出上面的大体算法步骤,就表示我们已经有了雏形,现在该如何实现找个数做基准数,把小于它的数移到它左边,把大于它的数移到它右边呢?
排除不满足的情况:
//已经不满足条件就代表可以不用递归了
if (left > right) {
return;
}
我们可以定义两个指针,用于遍历数组:
int start = left;//起点下标
int end = right;//终点下标
再找一个基准数:
int temp = nums[left];//把第一个数作为基准点
遍历代码:
/*如果左右指针还没有走到一起,代表还有位置没有遍历*/
while (start != end) {
//右指针先走,找到小于基准数的停止
while (start < end && nums[end] >= temp) {
end--; //这是往左移动指针
}
//左指针后走,找到大于基准数的停止
while (start < end && nums[start] <= temp) {
start++; //这是往右移动指针
}
//如果左右指针在未相遇时都找到了目标,则交换位置
if (start < end) {
int i = nums[start];
nums[start] = nums[end];
nums[end] = i;
}
//左右指针走到一起,则遍历结束
}
//把基准数与该点交换位置,因为这就是基准数的正确位置
nums[left] = nums[start];
nums[start] = temp;
如果还是不太清楚,不如自己动手试试!
拷贝完整代码:
//定义一个数组
static int[] nums = {5, 2, 6, 8, 4, 7, 9, 1};
static int n = nums.length - 1;
/**
* 递归的数据结构就是栈
* left right代表该段数组的起点和终点
*/
public void quick(int left, int right) {
//已经不满足条件就可以不用递归了
if (left > right) {
return;
}
//定义俩指针 用于移动
int start = left;//起点下标
int end = right;//终点下标
int temp = nums[left];//把第一个数作为基准点
pri(left, right);//打印此时的结果,不用在意
while (start != end) { //如果左右指针还没有走到一起,代表还有位置没有遍历
while (start < end && nums[end] >= temp) { //右指针先走,找到小于基准数的停止
end--; //这是往左在移动指针
}
while (start < end && nums[start] <= temp) { //左指针后走,找到大于基准数的停止
start++; //这是往右在移动指针
}
if (start < end) { //如果左右指针在未相遇时都找到了目标,则交换位置
int i = nums[start];
nums[start] = nums[end];
nums[end] = i;
}
}
//此时的left和right走到了一起
//把基准数与该点交换位置
nums[left] = nums[start];
nums[start] = temp;
prin(start);//打印输出,不用在意
//以上代码的作用就是把小于基准数的移到左边,把大于基准数的移到右边
quick(left, start - 1); //继续处理左边的,这里是一个递归的过程
quick(start + 1, right); //继续处理右边的 ,这里是一个递归的过程
}
/**
* 主程序入口
*/
public static void main(String[] args) {
new Test().quick(0, n);
}
/**
* 以下代码忽略即可,用于打印输出
*/
private void pri(int start, int end) {
StringBuffer s = new StringBuffer();
s.append("对数组 [");
while (start <= end) {
s.append(nums[start] + " ");
start++;
}
s.append("]");
s.append(" 排序");
System.out.print(s);
}
private void prin(int j) {
StringBuffer s = new StringBuffer();
s.append(", 排序后 [");
int start = 0;
while (start <= n) {
if (start == j) {
s.append("(" + nums[start] + ") ");
} else {
s.append(nums[start] + " ");
}
start++;
}
s.append("]");
s.append(" ");
System.out.println(s);
}
打印输出:
对数组 [5 2 6 8 4 7 9 1 ] 排序, 排序后 [4 2 1 (5) 8 7 9 6 ]
对数组 [4 2 1 ] 排序, 排序后 [1 2 (4) 5 8 7 9 6 ]
对数组 [1 2 ] 排序, 排序后 [(1) 2 4 5 8 7 9 6 ]
对数组 [2 ] 排序, 排序后 [1 (2) 4 5 8 7 9 6 ]
对数组 [8 7 9 6 ] 排序, 排序后 [1 2 4 5 6 7 (8) 9 ]
对数组 [6 7 ] 排序, 排序后 [1 2 4 5 (6) 7 8 9 ]
对数组 [7 ] 排序, 排序后 [1 2 4 5 6 (7) 8 9 ]
对数组 [9 ] 排序, 排序后 [1 2 4 5 6 7 8 (9) ]
让你一看就懂的快速排序算法(Java)的更多相关文章
- 快速排序算法 java 实现
快速排序算法 java 实现 快速排序算法Java实现 白话经典算法系列之六 快速排序 快速搞定 各种排序算法的分析及java实现 算法概念 快速排序是C.R.A.Hoare于1962年提出的一种划分 ...
- 排序算法系列:快速排序算法JAVA版(靠谱、清晰、真实、可用、不罗嗦版)
在网上搜索算法的博客,发现一个比较悲剧的现象非常普遍: 原理讲不清,混乱 啰嗦 图和文对不上 不可用,甚至代码还出错 为了不误人子弟耽误时间,推荐看一些靠谱的资源,如[啊哈!算法]系列: https: ...
- 排序系列 之 快速排序算法 —— Java实现
基本思想: 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变 ...
- 【排序算法】快速排序算法 Java实现
快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod). 基本思想 先从数组中找出一个数作为基 ...
- 快速排序算法Java版
网上关于快速排序的算法原理和算法实现都比较多,不过java是实现并不多,而且部分实现很难理解,和思路有点不搭调.所以整理了这篇文章.如果有不妥之处还请建议.首先先复习一些基础. 1.算法概念. ...
- 快速排序算法Java实现
1) 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行 示例: package ...
- 一看就懂的Android APP开发入门教程
一看就懂的Android APP开发入门教程 作者: 字体:[增加 减小] 类型:转载 这篇文章主要介绍了Android APP开发入门教程,从SDK下载.开发环境搭建.代码编写.APP打包等步骤 ...
- mysql取出现在的时间戳和时间时间戳转成人类看得懂的时间
mysql取出现在的时间戳和时间时间戳转成人类看得懂的时间,我们在mysql里面他封装了一个内置的时间戳转化的函数,比如我们现在的时间戳是:1458536709 ,"%Y-%m-%d&quo ...
- 一看就懂的ReactJs入门教程(精华版)
一看就懂的ReactJs入门教程(精华版) 现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和 ...
随机推荐
- 深入理解Java虚拟机01--概述
本课题是对<深入理解Java虚拟机>周志明 第二版的总结 具体可以参考:https://pan.baidu.com/s/1v_mPp--XV4u4rCBMkbR37A 第1版 可以忽略 ...
- leetcode-977. 有序数组的平方
leetcode-977. 有序数组的平方 (来自 120周赛) 题意 给定一个按非递减顺序排序的整数数组 A,返回每个数字的平方组成的新数组,要求也按非递减顺序排序. 示例 1: 输入:[-4,-1 ...
- DAY3(PYTHON)
一.or 和and的区别 X OR Y,如果X非0,则为X X OR Y,如果X为真,则为Y 二.continue 跳出当次循环 break 跳出循环 三.#输出1-2+3-4+5-6+......- ...
- Git基本操作和GtHub 特殊技巧
<GitHub 入门与实践> 笔记 了解GitHub Git 和 GitHub 的区别 在Git中,开发者将源代码存入名为"Git仓库"的资料库中,并加以使用.而Git ...
- (python)数据结构---元组
一.描述 一个有序的元素组成的集合 元组是不可变的线性数据结构 二.元组的相关操作 1.元组元素的访问 索引不可超界,否则抛异常IndexError 支持正负索引 t = (2, 3) print(t ...
- SQL SERVER数据库级的触发器
CREATE TRIGGER [Object_Change_Trigger_DDL] ON database FOR DROP_TABLE AS DECLARE @EventData AS xml; ...
- Mybatis 学习---${ }与#{ }获取输入参数的区别、Foreach的用法
一.Mybatis中用#{}和${}获取输入参数的区别 1.“#{}“和“${}”都可以从接口输入中的map对象或者pojo对象中获取输入的参数值.例如 <mapper namespace=&q ...
- oracle USING 用法
提问 using(xx)中可以接多个列吗? using(xx)中的列可以接表名或别名吗? 在使用using的语句中,select * 可以使用吗? 如果表有别名t,select t.* from ta ...
- Linux: 软件包管理之rpm与yum [转]
软件包的安装和卸载时很平常的事,但在Linux上面却不简单..Linux的其中一个哲学就是一个程序只做一件事,并且做好.组合小程序来完成复杂的任务,这样做有很多好处,但是各个小程序之间往往会存在着复杂 ...
- mysql中的升序和降序以及一个字段升序和一个字段降序
mySql中,升序为asc,降序为desc.例如: 升序:select * from 表名 order by 表中的字段 asc(mysql中默认是升序排列,可不写) 降序:select ...