zoukankan      html  css  js  c++  java
  • 快速排序算法过程及其代码优化

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

           

           如上图所示,我们选取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;
    	}
    }
    

      

  • 相关阅读:
    mysql复制那点事
    全排列问题
    56. Merge Interval
    2. Add Two Numbers
    20. Valid Parentheses
    121. Best Time to Buy and Sell Stock
    120. Triangle
    96. Unique Binary Search Trees
    91. Decode Ways
    72. Edit Distance
  • 原文地址:https://www.cnblogs.com/Booker808-java/p/9179290.html
Copyright © 2011-2022 走看看