快排的核心思想为每次确定一个数的位置,并使其左边的数均小于该数,右边的数均大于该书。之后对其左右两边进一步执行相同操作,直到排序结束。
程序主体为:
public static void quickSort(int[] nums, int begin, int end) {
if (begin < end) {
int mid = partition(nums, begin, end);
quickSort(nums, begin, mid - 1);
quickSort(nums, mid + 1, end);
}
}
Partition执行完成后,确定了一个数(这里默认为输入数组的第一个数)的位置。
以数组nums={5,2,7,3,6}为例:
I.quickSort(nums,0,4)
调用quickSort(nums,0,4)后,mid=partition(nums,0,4)=2,执行完partition后的数组分布如所示。接下来执行quickSort(nums,0,1),quickSort(3,4)。
II. quickSort(nums,0,1)&quickSort(nums,3,4)
quickSort(nums,0,1)过程中,mid=partition(nums,0,1)=1,完成partition后的数字分别如III左所示,得到最终结果。该部分接下去执行quickSort(nums,0,0)及quickSort(nums,1,1),在quickSort(nums,0,0)及quickSort(nums,1,1)中,(begin<end) == false,quickSort停止执行。
quickSort(nums,3,4)第类似于quickSort(nums,0,1)
具体流程如下,其中红色表示partition开始的位置,黄色表示partition完成后数字放置的位置:
Partition的功能为为某数找到指定位置。Partition(nums,0,4)的执行流程如下:
1. 基点为0,nums[0]=5。Int x = 5。将两个指针指向nums[1]和nums[4],如图中过程I
2. 先看右边的执行,6>5,不执行动作,右指针左移,如图中过程II。
3. 再看右指针,3<5,将3至于nums[0],nums[0]=3,如III。
4. 开始看左指针,2<5,不执行动作,左指针右移,如图中过程IV
5. 左指针指向nums[3]=7>x,交换左右指针中的值,如图中过程V
6. 右指针左移,与左指针重叠,循环结束,将x至于其中,完成partition。如图中VI所示
Partition函数:
public static int partition(int[] nums, int begin, int end) {
int i = begin, j = end;
int x = nums[i];
while (i < j) {
while (i < j && x < nums[j])
--j;
if (i < j)
nums[i++] = nums[j];
while (i < j && nums[i] < x)
++i;
if (i < j)
nums[j--] = nums[i];
}
nums[i] = x;
return i;
}
根据以上可知,快排的过程其实就是“不停调用partition对问题进行切割,不断减小问题规模”的过程。快排的非递归写法可通过stack存放partition中所需的begin及end完成。
整体代码:
import java.util.Stack;
public class Quick {
public static int partition(int[] nums, int begin, int end) {
int i = begin, j = end;
int x = nums[i];
while (i < j) {
while (i < j && x < nums[j])
--j;
if (i < j)
nums[i++] = nums[j];
while (i < j && nums[i] < x)
++i;
if (i < j)
nums[j--] = nums[i];
}
nums[i] = x;
return i;
}
// 递归
public static void quickSort(int[] nums, int begin, int end) {
if (begin < end) {
int mid = partition(nums, begin, end);
quickSort(nums, begin, mid - 1);
quickSort(nums, mid + 1, end);
}
}
// 非递归
public static void quickSort2(int[] nums, int begin, int end) {
Stack<Integer> stack = new Stack<Integer>();
int k = 0;
if (begin < end) {
stack.push(begin);
stack.push(end);
while (!stack.empty()) {
int j = stack.pop();
int i = stack.pop();
k = partition(nums, i, j);
if (i < k - 1) {
stack.push(i);
stack.push(k - 1);
}
if (k + 1 < j) {
stack.push(k + 1);
stack.push(j);
}
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = { 3, 5, 9, 7, 1, 6, 13, 22, 2 };
quickSort2(arr, 0, arr.length - 1);
for (int i : arr)
System.out.print(i + " ");
}
}