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;
    	}
    }
    

      

  • 相关阅读:
    汇编 Hello Window [菜鸟]疑问
    得到指定进程所有窗口。显示 影藏 置顶。
    汇编,SendMessage和WM_SETTEXT
    C#: 字段和局部变量的作用域冲突
    C#: 给方法传递参数
    C#:类和结构
    C#: string 类型
    Copy files to a folder which need have Administrator approve and overwrite the existing same readonly files
    C#:构造函数
    C#:数组, 命名空间, Main()方法
  • 原文地址:https://www.cnblogs.com/Booker808-java/p/9179290.html
Copyright © 2011-2022 走看看