让快速排序快速掌握

       直接切入主题,快速排序分为两过程 :挖抗填数 + 分治法 

       先说下分治法,顾名思义就是“分而治之”的核心思想。简单举个例子体会一下:现在有100个人需要按照身高排成一列。首先,定个身高基准1.7m(定得太高和太低都会打破平衡),高与1.7m的都站在一列的右端,低于1.7m的都站在一列的左端。1.7m即为左右端的分割基准。这样左右两端就可以同时按照身高进行排序了,排完之后合并起来不是很简单了。这样做,效率是不是大大提高了。

       

0 1 2 3 4 5 6 7
5 4 6 3 1 7 2 8

定义一个数组a,初始时,i = 0,j = 7 ,基准值X =a [0] = 5    (也可以设置为中间一个数,或者最后一个数)

可以假设基准值X为一个坑,需要用一个数往里面填,现在从j开始向前找一个<=X的数。当j=6时,将a[6]挖出填入到a[0]中,即a[0]=a[6],i ++ ; 接下来a[6]成了新的坑,我们从i开始向后找一个>X的数,当i=2时,将a[2]挖出填入到a[6]中,即a[6] = a[2],j --。

 数组变为

0 1 2 3 4 5 6 7
2 4 5 3 1 7 6 8

此时,i = 2 为一个坑,j=5,X=5。继续上面的步骤,从j = 5向前找一个<=X的数,当j=4时,将a[4] 挖出填入a[2],即a[2] = a[4], i++,a[4]成了新坑,我们从i =3开始向后找一个>X的数,当i = 4 = j 时。退出!由于a[4] 是上次挖的坑,因此需要把X给它填上。

此时数组变为

0 1 2 3 4 5 6 7
2 4 1 3 5 7 6 8

观察后,可以发现跟身高排队一样吧,基准值5的左边全是小于5的 ,而右边全是大于5的。只要将a[0-3]和a[5-7]这两个子数组重复上述步骤即可完成快速排序。

挖坑填数总结:

1.i =L; j = R; 将基准数挖出形成第一个坑a[i]。

2.j--由后向前找比它小的数,找到后挖出此数填前一个坑a[i]中。

3.i++由前向后找比它大的数,找到后也挖出此数填到前一个坑a[j]中。

4.再重复执行2,3二步,直到i==j,将基准数填入a[i]中。

思路清晰了,代码就好写了

package algorithm;

public class QuickSort {

	public static void quickSort(int arr[], int left, int right) {

		if (left < right) {

			int i = left, j = right, x = arr[left]; // X 为基准值,这里默认为第一个数

			while (i < j) {

				while (i < j && arr[j] >= x) { // 从右向左找第一个小于X的数
					j--; // 找不到就-1继续找
				}
				if (i < j) {
					arr[i++] = arr[j];
					// arry[i] = arry[j];
					// i++;
				}

				while (i < j && arr[i] < x) { // 从左向右找第一个大于X的数
					i++; // 找不到就+1继续找
				}
				if (i < j) {
					arr[j--] = arr[i];
					// arry[j] = arry[i];
					// j--;
				}

			}

			// 当i == j 时结束。 把基准值填入最后坑中
			arr[i] = x;

			// 这里采用分治法 继续让两个子数组继续排序
			quickSort(arr, left, i - 1);
			quickSort(arr, i + 1, right);
		}

	}
	
	public static void main(String[] args) {
		
		
		int[] reourse = {53,44,64,32,13,74,22,84};
		
		quickSort(reourse, 0, reourse.length -1);
		
		for (int i : reourse) {
			System.out.print(i + "\t");
		}
		
	}

}

猜你喜欢

转载自blog.csdn.net/weixin_42245930/article/details/82112746