让你一看就懂的快速排序算法(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) ]

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
阿里数据iOS端启动速度优化的一些经验
背景 7月26号我们阿里数据iOS端发布了4.4.0版本,这次版本主要是优化了性能,其中main()阶段的启动耗时优化成果比较明显,从之前的0.5-0.7秒,降低为目前的0.1-0.2秒(main()第一行代码到didFinishLaunchingWithOptions最后一行代码的耗时),用户体验提升明显。在这里梳理一下优化的一些经验,欢迎大家一起交流。 应用启动流程 iOS应用的启动可分为pre-main阶段和main()阶段,其中系统做的事情依次是: 1. pre-main阶段 1.1. 加载应用的可执行文件 1.2. 加载动态链接库加载器dyld(dynamic loader)1.3. dyld递归加载应用所有依赖的dylib(dynamic library 动态链接库) 2. main()阶段 2.1. dyld调用main() 2.2. 调用UIApplicationMain() 2.3. 调用applicationWillFinishLaunching2.4. 调用didFinishLaunchingWithOptions 启动耗时的测量 在进行优化之前,我们首先应该能测...
- 下一篇
如何设计和访问一个接口
1、 客户端验证(基本验证,防止服务端过多通讯) 2、 服务端验证(验证顺序要考虑:如开户接口,应该先验证基础参数,非空字段长度等;再验证数据库访问,如商户是否存在;最后验证外面请求,实名认证等。避免非法数据对数据库造成开销) 3、 事务标签,@Transactional下的代码应该行数最小,不包含数据准备、逻辑计算,不包含外部请求。(将数据准备、逻辑计算排除在事务标签之外,外部请求更不能放在事务中,考虑二阶段事务和事务补偿) 4、 慢SQL(解决方式:正确SQL写法、索引、缓存、冗余字段、表分区、归档、分库分表等等) 5、 严禁循环内SQL执行
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Red5直播服务器,属于Java语言的直播服务器
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS关闭SELinux安全模块
- Hadoop3单机部署,实现最简伪集群