【Java】快速排序的非递归实现
快速排序一般采用递归方法(详见快速排序及其优化),但递归方法一般都可以用循环代替。本文实现了java版的非递归快速排序。
更多:数据结构与算法合集
思路分析
采用非递归的方法,首先要想到栈的使用,通过阅读递归调用部分的代码,思考如何用栈来代替。递归调用的核心代码是 pivot = partition(a, low, high); 每次循环都必须包含这句核心代码,可以想到,如果要对该行代码实现循环,只能对low和high采取操作,所以我们在栈中压入low和high,每个循环弹出一对low和high,用于核心代码的实现,当栈空后就说明没有需要排序的部分了,结束循环。
下面是递归代码和根据递归代码修改成的非递归代码。
递归部分代码:
/**
* 递归调用
*/
public void qSort(int[] a, int low, int high) {
int pivot;
if (low >= high)
return; //原始递归操作
// pivot = partition(a, low, high); // 将数列一分为二
// qSort(a, low, pivot - 1); // 对低子表排序
// qSort(a, pivot + 1, high); // 对高子表排序 // 优化递归操作
while (low < high) {
pivot = partition(a, low, high); // 将数列一分为二
qSort(a, low, pivot - 1); // 对低子表排序
low = pivot + 1;
}
}
修改成的非递归代码:
/**
* 非递归
*/
public void qSort2(int[] a, int low, int high) {
int pivot;
if (low >= high)
return;
Stack<Integer> stack = new Stack<Integer>();
stack.push(low);
stack.push(high);
while (!stack.empty()) {
// 先弹出high,再弹出low
high = stack.pop();
low = stack.pop();
pivot = partition(a, low, high);
// 先压low,再压high
if (low < pivot - 1) {
stack.push(low);
stack.push(pivot - 1);
}
if (pivot + 1 < high) {
stack.push(pivot + 1);
stack.push(high);
}
}
}
注意点:栈弹出的顺序与压入的顺序相反,要小心栈的压入与弹出操作。
完整Java代码
(含测试代码)
import java.util.Arrays;
import java.util.Stack; /**
*
* @Description 快速排序的递归与非递归实现
*
* @author yongh
* @date 2018年9月14日 下午2:39:00
*/
public class QuickSort {
public void quickSort(int[] a) {
if (a == null)
return;
qSort(a, 0, a.length - 1);
}
/**
* 递归
*/
public void qSort(int[] a, int low, int high) {
int pivot;
if (low >= high)
return; //原始递归操作
// pivot = partition(a, low, high); // 将数列一分为二
// qSort(a, low, pivot - 1); // 对低子表排序
// qSort(a, pivot + 1, high); // 对高子表排序 // 优化递归操作
while (low < high) {
pivot = partition(a, low, high); // 将数列一分为二
qSort(a, low, pivot - 1); // 对低子表排序
low = pivot + 1;
}
} public void quickSort2(int[] a) {
if (a == null)
return;
qSort2(a, 0, a.length - 1);
}
/**
* 非递归
*/
public void qSort2(int[] a, int low, int high) {
int pivot;
if (low >= high)
return;
Stack<Integer> stack = new Stack<Integer>();
stack.push(low);
stack.push(high);
while (!stack.empty()) {
// 先弹出high,再弹出low
high = stack.pop();
low = stack.pop();
pivot = partition(a, low, high);
// 先压low,再压high
if (low < pivot - 1) {
stack.push(low);
stack.push(pivot - 1);
}
if (pivot + 1 < high) {
stack.push(pivot + 1);
stack.push(high);
}
}
} /**
* 对数组a中下标从low到high的元素,选取基准元素pivotKey,
* 根据与基准比较的大小,将各个元素排到基准元素的两端。
* 返回值为最后基准元素的位置
*/
public int partition(int[] a, int low, int high) { // 三数取中,将中间元素放在第一个位置
if (a[low] > a[high])
swap(a, low, high);
if (a[(low + high) / 2] > a[high])
swap(a, (low + high) / 2, high);
if (a[low] < a[(low + high) / 2])
swap(a, (low + high) / 2, low); int pivotKey = a[low]; // 用第一个元素作为基准元素
while (low < high) { // 两侧交替向中间扫描
while (low < high && a[high] >= pivotKey)
high--;
a[low] = a[high];
// swap(a, low, high); //比基准小的元素放到低端
while (low < high && a[low] <= pivotKey)
low++;
a[high] = a[low];
// swap(a, low, high); //比基准大的元素放到高端
}
a[low] = pivotKey; // 在中间位置放回基准值
return low; // 返回基准元素所在位置
} public void swap(int[] a, int i, int j) {
int temp;
temp = a[j];
a[j] = a[i];
a[i] = temp;
} // =========测试代码=======
//测试的为非递归方法quickSort2()
public void test1() {
int[] a = null;
quickSort2(a);
System.out.println(Arrays.toString(a));
} public void test2() {
int[] a = {};
quickSort2(a);
System.out.println(Arrays.toString(a));
} public void test3() {
int[] a = { 1 };
quickSort2(a);
System.out.println(Arrays.toString(a));
} public void test4() {
int[] a = { 3, 3, 3, 3, 3 };
quickSort2(a);
System.out.println(Arrays.toString(a));
} public void test5() {
int[] a = { -3, 6, 3, 1, 3, 7, 5, 6, 2 };
quickSort2(a);
System.out.println(Arrays.toString(a));
} public static void main(String[] args) {
QuickSort demo = new QuickSort();
demo.test1();
demo.test2();
demo.test3();
demo.test4();
demo.test5();
}
}
null
[]
[]
[, , , , ]
[-, , , , , , , , ]
QuickSort
收获
递归改为非递归,联想到栈的使用,根据对核心代码的循环,确定栈中存储什么数据。
更多:数据结构与算法合集
【Java】快速排序的非递归实现的更多相关文章
- 排序算法练习--JAVA(插入、直接选择、冒泡、快速排序、非递归快速排序)
排序算法是数据结构中的经典算法知识点,也是笔试面试中经常考察的问题,平常学的不扎实笔试时候容易出洋相,回来恶补,尤其是碰到递归很可能被问到怎么用非递归实现... package sort; impor ...
- 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,循环控制及其优化
上两篇博客 8皇后以及N皇后算法探究,回溯算法的JAVA实现,递归方案 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,数据结构“栈”实现 研究了递归方法实现回溯,解决N皇后问题,下面我们来 ...
- 【Java】 归并排序的非递归实现
归并排序可以采用递归方法(见:归并排序),但递归方法会消耗深度位O(longn)的栈空间,使用归并排序时,应该尽量使用非递归方法.本文实现了java版的非递归归并排序. 更多:数据结构与算法合集 思路 ...
- 算法笔记_013:汉诺塔问题(Java递归法和非递归法)
目录 1 问题描述 2 解决方案 2.1 递归法 2.2 非递归法 1 问题描述 Simulate the movement of the Towers of Hanoi Puzzle; Bonus ...
- 自己写算法---java的堆的非递归遍历
import java.io.*; import java.util.*; public class Main { public static void main(String args[]) { S ...
- 数据结构二叉树的递归与非递归遍历之java,javascript,php实现可编译(1)java
前一段时间,学习数据结构的各种算法,概念不难理解,只是被C++的指针给弄的犯糊涂,于是用java,web,javascript,分别去实现数据结构的各种算法. 二叉树的遍历,本分享只是以二叉树中的先序 ...
- 二叉树3种递归和非递归遍历(Java)
import java.util.Stack; //二叉树3种递归和非递归遍历(Java) public class Traverse { /******************一二进制树的定义*** ...
- JAVA 遍历文件夹下的所有文件(递归调用和非递归调用)
JAVA 遍历文件夹下的所有文件(递归调用和非递归调用) 1.不使用递归的方法调用. public void traverseFolder1(String path) { int fileNum = ...
- Java实现非递归删除目录
最近在学C#的文件系统, 发现C#的文件系统貌似比java的东西少一点, 居然连删除目录都直接做好封装了, 想到学java的时候还要自己写递归删除, 好像没写过非递归的,就在网上查了下, 关于非递归删 ...
随机推荐
- 洛谷P3241 开店
题意:紫妹和幽香是17岁的少女,喜欢可爱的东西. 给定一棵树,有点权,边权.每次求所有权值在[l, r]范围内的点到点x的距离和.强制在线. 解:动态点分治怎么搞啊...... 一开始想的是权值的限制 ...
- vue-devtools/安装vue-devtools
一.在github上下载压缩包,github下载地址:https://github.com/vuejs/vue-devtools 二.解压到本地的某盘 三.用你的npm中进入该文件夹下 在npm中执行 ...
- solr与mysql数据同步的方案
1.使用activeMQ http://blog.csdn.net/zhou2s_101216/article/details/77855413 2.通过配置实现定时同步 http://blog.cs ...
- Dubbo学习笔记6:Dubbo增强SPI与SPI中扩展点自动包装的实现原理
在Dubbo整体架构分析中介绍了Dubbo中除了Service和Config层为API外,其他各层均为SPI,为SPI意味着下面各层都是组件化可以被替换的,也就是扩展性比较强,这也是Dubbo比较好的 ...
- SQL语句(六)成批导入导出数据
(六) 成批导入导出数据 假设已经存在teaching数据库, 存在一张Student表,如图: 右键teaching->任务->导入数据 下一步->数据源(Microsoft Ex ...
- html5 canvas裁剪区域
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 阿里云Linux服务器安装 nginx+mysql+php
阿里云Linux服务器安装 nginx+mysql+php步骤1.登录服务器2.下载安装包3.将安装包上传到服务器的/home目录下 注:使用rz sz命令进行本地和服务器间的上传.下载,安装命令yu ...
- CSS 实现图片灰度效果
非原创-从网上收索出来的文章 CSS实现图片灰度效果就是通过CSS样式让彩色图片呈现为灰色,相当于把一张图像的颜色模式调整为灰度,CSS可以通过以下几种方法来实现灰度效果. 方式1. IE滤镜 img ...
- Jad查看源码
需要者两个文件:下载地址:http://pan.baidu.com/s/11qq4I 1,解压jar包 有两个文件 分别是net.sf.jadclipse_3.3.0 jad.exe 文件 2,找到m ...
- Docker01 CentOS配置Docker
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何 ...