快速排序可以说是20世纪最伟大的算法之一了。相信都有所耳闻,它的速度也正如它的名字那样,是一个非常快的算法了。当然它也后期经过了不断的改进和优化,才被公认为是一个值得信任的非常优秀的算法。
本文将结合快速排序的三方面进行比较和深入解析。
快速排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 public class QuickSort { public static void QuickSort (int [] arr,int l,int r) { if (l>=r) return ; int p = partition(arr,l,r); QuickSort(arr,l,p-1 ); QuickSort(arr,p+1 ,r); } public static int partition (int [] arr, int l, int r) { swap(arr, l, (int ) (Math.random() * (r - l + 1 )) + l); int v = arr[l]; int j = l; for (int i = j +1 ;i<=r;i++){ if (arr[i] < v){ j++; swap(arr,i,j); } } swap(arr,l,j); return j; } public static void swap (int [] arr,int i,int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } public static void printArray (int [] arr) { for (int i = 0 ; i < arr.length; i++){ System.out.print( arr[i] ); System.out.print( ' ' ); } System.out.println(); return ; } public static void main (String[] args) { int [] arr = {4 ,3 ,12 ,12 }; QuickSort(arr,0 ,arr.length-1 ); printArray(arr); } }
双路快速排序
若果数组中含有大量重复的元素,则partition很可能把数组划分成两个及其不平衡的两部分,时间复杂度退化成O(n²)。这时候应该把小于v和大于v放在数组两端
实际上把等于的部分分散到了数组两端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 public class QuickSort2Ways { private static int partition (int [] arr, int l, int r) { swap(arr, l, (int ) (Math.random() * (r - l + 1 )) + l); int v = arr[l]; int i = l + 1 , j = r; while (true ) { while (i <= r && arr[i] < v) i++; while (j >= l + 1 && arr[j] > v) j--; if (i > j) break ; swap(arr, i, j); i++; j--; } swap(arr, l, j); return j; } private static void QuickSort2Ways (int [] arr, int l, int r) { int p = partition(arr, l, r); QuickSort(arr, l, p - 1 ); QuickSort(arr, p + 1 , r); } private static void swap (int [] arr, int i, int j) { int t = arr[i]; arr[i] = arr[j]; arr[j] = t; } public static void printArray (int [] arr) { for (int i = 0 ; i < arr.length; i++) { System.out.print(arr[i]); System.out.print(' ' ); } System.out.println(); return ; } public static void main (String[] args) { int [] arr = {4 , 3 , 12 , 12 }; QuickSort2Ways(arr, 0 , arr.length - 1 ); printArray(arr); } }
三路快速排序
数组分成三个部分,大于v 等于v 小于v
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 public class QuickSort3Ways { private static void QuickSort3Ways (int [] arr, int l, int r) { swap( arr, l, (int )(Math.random()*(r-l+1 )) + l ); int v = arr[l]; int lt = l; int gt = r + 1 ; int i = l+1 ; while ( i < gt ){ if ( arr[i] < v){ swap( arr, i, lt+1 ); i ++; lt ++; } else if ( arr[i] > v ){ swap( arr, i, gt-1 ); gt --; } else { i ++; } } swap( arr, l, lt ); QuickSort3Ways(arr, l, lt-1 ); QuickSort3Ways(arr, gt, r); } private static void swap (int [] arr, int i, int j) { int t = arr[i]; arr[i] = arr[j]; arr[j] = t; } public static void printArray (int [] arr) { for (int i = 0 ; i < arr.length; i++) { System.out.print(arr[i]); System.out.print(' ' ); } System.out.println(); return ; } public static void main (String[] args) { int [] arr = {4 , 3 , 12 , 12 }; QuickSort3Ways(arr, 0 , arr.length - 1 ); printArray(arr); } }