码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-08-19 16:56:12      阅读:114      评论:0      收藏:0      [点我收藏+]

标签:快排   递归   非递归   partition   分治   

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

程序主体为:

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

}



版权声明:本文为博主原创文章,未经博主允许不得转载。

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

标签:快排   递归   非递归   partition   分治   

原文地址:http://blog.csdn.net/miaoyunzexiaobao/article/details/47781079

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!