? ? ? ?快速排序是我们大一进入学校就会的东西,但我发现自己到了大学之后学东西非常 生硬,都是被别人灌输的,缺少了自己思考的过程,这几天被左神一语惊醒,我们学习算法应该是一个思考与探索的过程,不是简单的把这道题AC了就完事了,那我们大学之前那么辛苦可不是为了来大学玩的,所以以后要学会思考和学会探索;
? ? ? ?首先今天我们来讲的是快速排序,这里用三种方法来写快排的;
?①设定一个标志,两个 哨兵分别从两端开始行走的方法,主代码如下:
class="java" name="code">public static void quickSort(int[] arr,int l,int r){ if ( l < r ){ //随机出标志数 swap1(arr, l + (int) (Math.random() * (r - l + 1)), r); int q = partition(arr ,l , r); quickSort(arr,l,q-1); quickSort(arr,q+1,r); } } public static int partition(int[] arr,int l,int r){ int p = arr[l];//设置标志位置 int i = l;//左哨兵 int j = r;//右哨兵 while (i < j){ while (arr[j] >= p && i < j){ j--; } if (i<j){ swap1(arr,i,j); } while (arr[i] <= p && i < j){ i++; } if (i<j){ swap1(arr,i,j); } } return i; }
?②把最右边的设置 为标志位,一个哨兵 从最左侧依次进行比较,把 数组 分为两个区,代码 如下:
public static void quickSort2(int[] arr,int l,int r){ if ( l < r ){ //随机产生标志位 swap1(arr, l + (int) (Math.random() * (r - l + 1)), r); int q = partition2(arr,l,r); quickSort(arr,l,q-1); quickSort(arr,q+1,r); } } public static int partition2(int[] arr,int l,int r){ int i = l-1; int j = r; while (l < j){ //每次把最右边的设置为标志位,这样减少了额外空间 if (arr[l]<=arr[r]){ i++; swap1(arr,i,l); l++; }else{ j--; swap1(arr,j,l); } } swap1(arr,j,r); return i+1; }
?③把数组分为三部分,大于区,小于区和等于区,这样会减少比较的次数,代码如下:
public static void quickSort1(int[] arr,int l,int r){ if ( l < r ){ swap1(arr, l + (int) (Math.random() * (r - l + 1)), r); int[] q = partition1(arr,l,r); quickSort(arr,l,q[0]-1); quickSort(arr,q[0]+1,r); } } //划分数组的优化算法,把一个数组分为三个区,大于区,小于区和等于区 public static int[] partition1(int[] arr,int l,int r){ int i = l-1; int j = r; while (l < j){ //每次把最右边的设置为哨兵,这样减少了额外空间 if (arr[l]<arr[r]){ swap1(arr,++i,l++); }else if (arr[l]>arr[r]){ swap1(arr,--j,l); }else { l++; } } swap1(arr,j,r); return new int[] {i+1,j}; }
?完整代码如下:
package study.tao.sort; import java.util.Arrays; /** * Created by Taoyongpan on 2017/11/13. * 快速排序及其优化,我们一般快排的时候会把一个数组 分为两个区 * 大于等于和小于两个区,现在我们要做的是讲一个数组分为三个区,大于,等于和小于三个区 * 这样做的好处是每次把相等的数放在中间位置,这样会减少比较次数 */ public class QuickSort { //随机产生一个数组 大小为maxSize,最大值为maxValue的数组 public static int[] generateRandomArray(int maxSize,int maxValue){ if (maxSize<=0){ return null; } int[] arr = new int[(int)((maxSize+1)*Math.random())]; for (int i = 0 ; i < arr.length ; i++){ arr[i] = (int) ((maxValue+1)*Math.random()); } return arr; } //数组的输出函数 public static void printArray(int[] arr){ if (arr==null){ return; } for (int j = 0 ; j < arr.length ; j++){ System.out.print(arr[j]+" "); } System.out.println(); } //复制函数 public static int[] copyArray(int[] arr){ int[] res = new int[arr.length]; if (arr == null){ return null; } for (int i = 0 ; i < arr.length ; i++){ res[i] = arr[i]; } return res; } //交换函数 //位运算进行交换 public static void swap(int[] arr,int i,int j){ arr[i] = arr[i]^arr[j]; arr[j] = arr[i]^arr[j]; arr[i] = arr[i]^arr[j]; } //需要额外空间的交换函数 public static void swap1(int[] arr,int i,int j){ int temp; temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } //系统的比较函数 public static void arraySort(int[] arr){ Arrays.sort(arr); } //比较自己写的排序函数和系统的排序函数结果是否相等 public static boolean isEqual(int[] arr1,int[] arr2){ if ((arr1 == null && arr2 !=null)||(arr1 !=null && arr2 ==null)||( arr1 == null && arr2 == null)){ return false; } if (arr1.length != arr2.length){ return false; } for (int i = 0 ; i <arr1.length;i++){ if (arr1[i] != arr2[i]){ return false; } } return true; } //快速排序 public static void quickSort(int[] arr,int l,int r){ if ( l < r ){ swap1(arr, l + (int) (Math.random() * (r - l + 1)), r); int q = partition(arr ,l , r); quickSort(arr,l,q-1); quickSort(arr,q+1,r); } } public static void quickSort1(int[] arr,int l,int r){ if ( l < r ){ swap1(arr, l + (int) (Math.random() * (r - l + 1)), r); int[] q = partition1(arr,l,r); quickSort(arr,l,q[0]-1); quickSort(arr,q[0]+1,r); } } public static void quickSort2(int[] arr,int l,int r){ if ( l < r ){ swap1(arr, l + (int) (Math.random() * (r - l + 1)), r); int q = partition2(arr,l,r); quickSort(arr,l,q-1); quickSort(arr,q+1,r); } } //定位函数 //划分数组,用两个哨兵的方法 public static int partition(int[] arr,int l,int r){ int p = arr[l];//设置哨兵位置 int i = l; int j = r; while (i < j){ while (arr[j] >= p && i < j){ j--; } if (i<j){ swap1(arr,i,j); } while (arr[i] <= p && i < j){ i++; } if (i<j){ swap1(arr,i,j); } } return i; } //划分数组的优化算法,把一个数组分为三个区,大于区,小于区和等于区 public static int[] partition1(int[] arr,int l,int r){ int i = l-1; int j = r; while (l < j){ //每次把最右边的设置为哨兵,这样减少了额外空间 if (arr[l]<arr[r]){ swap1(arr,++i,l++); }else if (arr[l]>arr[r]){ swap1(arr,--j,l); }else { l++; } } swap1(arr,j,r); return new int[] {i+1,j}; } //划分数组的一级优化 public static int partition2(int[] arr,int l,int r){ int i = l-1; int j = r; while (l < j){ //每次把最右边的设置为哨兵,这样减少了额外空间 if (arr[l]<=arr[r]){ i++; swap1(arr,i,l); l++; }else{ j--; swap1(arr,j,l); } } swap1(arr,j,r); return i+1; } //主函数 public static void main(String[] args){ int maxSize = 100; int maxValue = 100; int maxTime = 3; boolean flag = true; int[] arr1 = generateRandomArray(maxSize,maxValue);//随机生成数组 int[] arr2 = copyArray(arr1);//把数组1中的值复制到arr2中 quickSort(arr1,0,arr1.length-1); arraySort(arr2); quickSort1(arr1,0,arr1.length-1); arraySort(arr2); quickSort2(arr1,0,arr1.length-1); arraySort(arr2); System.out.println(isEqual(arr1,arr2)?"succeed":"failed"); printArray(arr1); } }
?