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 stack = new Stack();

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 stack = new Stack();

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();

}

}

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

null[]

[1]

[3, 3, 3, 3, 3]

[-3, 1, 2, 3, 3, 5, 6, 6, 7]

QuickSort

收获

递归改为非递归,联想到栈的使用,根据对核心代码的循环,确定栈中存储什么数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值