快排详解、递归与非递归的实现

快排的核心思想为每次确定一个数的位置,并使其左边的数均小于该数,右边的数均大于该书。之后对其左右两边进一步执行相同操作,直到排序结束。

程序主体为:

	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 + " ");
	}

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值