我们通常见到的快速排序为递归版本,并没有关注非递归的方式。但非递归版本也是很好实现的,因为递归的本质是栈。在非递归实现的过程中,借助栈来保存中间变量就可以实现非递归了。在这里中间变量也就是通过Pritation函数划分之后分成左右两部分的首尾指针,只需要保存这两部分的首尾指针即可。具体代码如下
import java.util.Arrays;
import java.util.Stack;
/**
* Time: 2019-06-13
* Author: snowy
* 快速排序, 递归版本和非递归版本
* */
public class QuickSort {
// 确定位置
public static int partition(int[] nums, int left, int right) {
int temp = nums[left];
while(left < right) {
while(left < right && nums[right] >= temp)
right --;
if(left < right) // 如果队尾元素小于temp了,需要将其赋值给left的位置,因为当前这个位置left上可以认为值是无效的
nums[left] = nums[right];
while(left < right && nums[left] <= temp)
left ++;
if(left < right)
nums[right] = nums[left];
}
nums[right] = temp;
return left;
}
// 快排递归版本
public static void QuickSort(int[] nums, int start, int end) {
if(start >= end)
return;
int station = partitation(nums, start, end);
QuickSort(nums, start, station - 1);
QuickSort(nums, station + 1, end);
}
// 快排的非递归写法
public static void QuickSort_iter(int[] nums, int left, int right) {
if(nums == null || left >= right)
return;
Stack<Integer> stack = new Stack<>();
// int left = 0, right = nums.length - 1;
int i , j;
// 注意顺序
stack.push(left);
stack.push(right);
while(!stack.isEmpty()) {
// 这里需要注意顺序呀
j = stack.pop(); // 先弹出右指针
i = stack.pop(); // 在弹出左指针
if(i < j) {
int station = partition(nums, i, j);
if(station > i) {
stack.push(i);
stack.push(station - 1);
}
if(station < j) {
stack.push(station + 1);
stack.push(j);
}
}
}
}
public static void main(String[] args) {
int[] nums = {3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48};
System.out.println("排序前:" + Arrays.toString(nums));
QuickSort_iter(nums, 0, nums.length - 1);
System.out.println("排序后:" + Arrays.toString(nums));
}
}