快速排序算法过程及其代码优化

       快速排序,就是我们选取数组里的一个基数,根据基数,我们把整个数组分为两部分,一边是大于该基数的,一边是小于该基数的。

       

       如上图所示,我们选取6作为基数,经过一系列的排序后,6处于它在排序好的数组中应该存在的位置,两边分别是大于它和小于它的数字,然后我们再分别对两边分别递归快排,之后再对两边分别递归快排,之后全部汇总,得到一个有序的数组。但是我们有个问题,就是这个6不止一个,可能有两三个,那么这个时候就会出现这种情况:

      1   2   4   6   6   6   7

                        

       这个时候,我们如果还是按照之前的,从lo和hi汇合的地方对两边子部分分别递归快排,这个时候两边的6就显得很多余,因为他们可以不用加入到快排的任务中去,只需要从三个6的两边进行排序即可。所以我们这个时候就要对快排进行改进!

普通快排:

public class QuickSort {
	public static void sort(int[] arr, int low, int high) {
		if (low >= high) {
			return;
		}
		int index = arr[low];
		int i = low;
		int j = high;
		while (i < j) {
			while (i < j && arr[j] >= index) {
				j--;
			}
			if (i < j) {
				arr[i++] = arr[j];
				arr[j] = index;
			}
			while (i < j && arr[i] <= index) {
				i++;
			}
			if (i < j) {
				arr[j--] = arr[i];
				arr[i] = index;
			}
		}
		sort(arr, low, i - 1);
		sort(arr, i + 1, high);
	}
}

       我们定义两个指针less和more,从less负责掌管左边(比基数小的数),more负责掌管右边(比基数大的数)。

 

       1   2   4   6   6   6   7

 

                          

 

                less     L   more

这时我们只需要对less和less前面的部分,more后面的部分进行排序,这样我们就不必和之前一样,因为基数重复而需要进行额外的一些判断了。但是还有一个问题就是,如果我们选取的基数,它所处的位置在排序好的数组里处于比较极端的位置(比如处于第一个,或者是最后一个),那这个时候我们的排序就有没有起到分而治之的作用,所以我们可以通过random来做到随机选取数组里的一个数来作为基数,这样我们就很难会出现上面的情况!

 

改进后的代码:

public class QuickSortImprove {

	public static void quickSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}
		quickSort(arr, 0, arr.length - 1);
	}

	public static void quickSort(int[] arr, int l, int r) {
		if (l < r) {
			// 选取最后一个数字作为基数
			swap(arr, l + (int) (Math.random() * (r - l + 1)), r);
			int[] p = partition(arr, l, r);
			quickSort(arr, l, p[0]);
			quickSort(arr, p[1] + 1, r);
		}
	}

	public static int[] partition(int[] arr, int l, int r) {
		int less = l - 1;
		int more = r;
		while (l < more) {
			if (arr[l] < arr[r]) {
				swap(arr, ++less, l++);
			} else if (arr[l] > arr[r]) {
				swap(arr, --more, l);
			} else {
				l++;
			}
		}
		swap(arr, more, r);
		int[] res = { less, more };
		return res;
	}

	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}
}

  

posted @ 2018-06-13 18:40  Booker808  阅读(228)  评论(0编辑  收藏  举报