快速排序不使用递归实现
思路分析
- 核心思想不改变,不采用递归,首先需要把节点分离出来,单路和双路核心算法抽取出来
- 将快速排序的左右节点放入数组,由于普通数组长度限定,我们又不知道要分离多少次,所以需要手动扩容
- 只需要判断节点数组是否为空即可
快速排序基准点分离
单路分离节点
/**
* 单路排序节点分离
*/
public static int ontWay(int[] arr, int start, int end) {
int j = start;
for (int i = start; i < end; i++) {
if (arr[i] < arr[end]) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
j++;
}
}
int temp = arr[end];
arr[end] = arr[j];
arr[j] = temp;
return j;
}
双路快速排序分离
/**
* 双路排序节点分离
*/
public static int twoWay(int[]arr, int start, int end) {
int s = start;
int e = end;
int temp = arr[start];
while (s < e) {
while (s < e && arr[e] > temp) {
e--;
}
if (s < e) {
arr[s] = arr[e];
s++;
}
while (s < e && arr[s] < temp) {
s++;
}
if (s < e) {
arr[e] = arr[s];
e--;
}
}
arr[s] = temp;
return s;
}
数组扩容
可以采用栈和队列思想解决
先进先出,后进后出
/**
* 尾部压入元素
*/
public static int[][] push(int[][] arr, int[] element) {
int[][] newArr = new int[arr.length + 1][2];
int i = 0;
for (; i < arr.length; i++) {
newArr[i] = arr[i];
}
newArr[i] = element;
return newArr;
}
/**
* 尾部弹出元素
*/
public static int[][] pop(int[][] arr) {
int[][] newArr = new int[arr.length - 1][2];
for (int i = 0; i < newArr.length; i++) {
newArr[i] = arr[i];
}
return newArr;
}
/**
* 头部压入元素
*/
public static int[][] unshift(int[][] arr, int[] element) {
int[][] newArr = new int[arr.length + 1][2];
for (int i = 0; i < arr.length; i++) {
newArr[i + 1] = arr[i];
}
newArr[0] = element;
return newArr;
}
/**
* 头部删除元素
*/
public static int[][] shift(int[][] arr) {
int[][] newArr = new int[arr.length - 1][2];
for (int i = 0; i < newArr.length; i++) {
newArr[i] = arr[i + 1];
}
return newArr;
}
我们把数组扩容四种基本情况编写完成,即可很轻松实现头进尾出,还是头进头出,灵活组合
话不多说上代码
/**
* 不使用递归,实现快速排序
* 栈思想:先进先出
*/
public static void quickSort2(int[] arr) {
// 范围列表(栈)
int[][] rangeList = {{0, arr.length - 1}};
while (rangeList.length > 0) {
// 尾元素出栈
int[] range = rangeList[rangeList.length - 1];
rangeList = pop(rangeList);
int start = range[0];
int end = range[1];
int cutoff = twoWay(arr, start, end);
// 如果左边范围有效,尾部入栈
if (start < cutoff - 1) {
rangeList = push(rangeList, new int[] {start, cutoff - 1});
}
// 如果右边范围有效,尾部入栈
if (end > cutoff + 1) {
rangeList = push(rangeList, new int[] {cutoff + 1, end});
}
}
}
/**
* 不使用递归,实现快速排序
* 队列思想,先进先出
*/
public static void quickSort3(int[] arr) {
int[][] rangList = {{0, arr.length - 1}};
while (rangList.length > 0) {
// 头部出列
int[] range = rangList[0];
rangList = shift(rangList);
int start = range[0];
int end = range[1];
int cutoff = twoWay(arr, start, end);
// 如果左边范围有效,头部入列
if (start < cutoff - 1) {
rangList = unshift(rangList, new int[] {start, cutoff - 1});
}
// 右边范围有效,头部入列
if (end > cutoff + 1) {
rangList = unshift(rangList, new int[] {cutoff + 1, end});
}
}
}