使用分割思想实现快速排序算法
本文记录快速排序算法的一个精美实现,关于其中的一些优化或者思路请参考如下资料:
http://www.cnblogs.com/hapjin/p/5518922.html
http://blog.csdn.net/hapjin/article/details/49785477
http://blog.csdn.net/hapjin/article/details/49201341
快排算法的实现思路:
1,快排数组的范围 [0,arr.length-1],选出pivot元素后,pivot元素的位置就确定不变了。因此,pivot元素的index将数组分成2部分,[left, pivot_index-1]、[pivot_index+1,right]
2,三数取中算法选择piovt元素,将三个数中的最小值放在 arr[left],中间值放在arr[center],最大值放在arr[right],然后返回 中间值 作为pivot元素。
3,partition算法将 那些比 pivot 小的元素放在 pivot_index的左边,把那些比 pivot大的元素放在 pivot_index 右边
1 public class QuickSort { 2 3 public static void quickSort(int[] arr) { 4 quickSort(arr, 0, arr.length-1); 5 } 6 7 public static void quickSort(int[] arr, int left, int right) { 8 if (left < right) {//递归退出条件,不再继续"分割"数组 9 //pivot 元素位置已经完全固定 10 int pivot_index = partition(arr, left, right); 11 quickSort(arr, left, pivot_index - 1); 12 quickSort(arr, pivot_index + 1, right); 13 } 14 } 15 16 public static int partition(int[] arr, int left, int right) { 17 int pivot = media3(arr, left, right); 18 int i = left; 19 int j = right; 20 //一轮分割 21 for (; ; ) { 22 //--j 因为 23 while (arr[++i] < pivot){} 24 while (arr[--j]> pivot){} 25 if (i < j) { 26 //找到了一个需要交换的元素 27 swap(arr, i, j); 28 }else { 29 break; 30 } 31 } 32 // 33 return i; 34 } 35 36 public static int media3(int[] arr, int left, int right) { 37 if (arr.length == 1) { 38 //只有一个元素的数组 39 return arr[0]; 40 } 41 if (left == right) { 42 //退出条件 43 return arr[left]; 44 } 45 int center = (left + right) / 2; 46 //arr[left] 存放三个数中的最小值 47 if (arr[left] > arr[center]) { 48 swap(arr, left, center); 49 } 50 if (arr[left] > arr[right]) { 51 swap(arr, left, right); 52 } 53 54 //arr[center]存放三个数中的中间值 55 if (arr[center] > arr[right]) { 56 swap(arr,center,right); 57 } 58 int media = arr[center]; 59 return media; 60 } 61 62 public static void swap(int[] arr, int low, int high) { 63 int tmp = arr[low]; 64 arr[low] = arr[high]; 65 arr[high] = tmp; 66 } 67 68 public static void main(String[] args) { 69 int[] arr2 = {1,-1,0,2,-2}; 70 quickSort(arr2); 71 for (int i : arr2) { 72 System.out.print(i + " "); 73 } 74 } 75 }
一个小的优化:
public class QuickSort{ //分割数组,将数组分成两部分. 一部分比pivot(枢轴元素)大,另一部分比pivot小 private static int parition(int[] arr, int left, int right){ int pivot = media3(arr, left, right); int i = left; int j = right - 1;//注意 ,在 media3()中 arr[right-1]就是 pivot //应对特殊情况下的数组,比如数组长度 小于3 if(i >= j) return i; for(;;) { while(arr[++i] < pivot){} while(arr[--j] > pivot){} if(i < j) swap(arr, i, j); else break; } swap(arr, i, right-1);//restore pivot 将枢轴元素放置到合适位置:arr左边元素都比pivot小,右边都比pivot大 return i;// 返回 pivot的 索引 } //三数取中,用在快排中随机选择枢轴元素时 private static int media3(int[] arr, int left, int right){ if(arr.length == 1) return arr[0]; if(left == right) return arr[left]; int center = (left + right) / 2; //找出三个数中的最小值放到 arr[left] if(arr[center] < arr[left]) swap(arr, left, center); if(arr[right] < arr[left]) swap(arr, left, right); //将 中间那个数放到 arr[media] if(arr[center] > arr[right]) swap(arr, center, right); swap(arr, center, right-1);//尽量将大的元素放到右边--将privot放到右边, 可简化 分割操作(partition). return arr[right-1];//返回中间大小的那个数 } private static void swap(int[] arr, int left, int right){ int tmp = arr[left]; arr[left] = arr[right]; arr[right] = tmp; } public static void quickSort(int[] arr){ quickSort(arr, 0, arr.length - 1); } private static void quickSort(int[] arr, int left, int right){ if(left < right){ int pivot_index = parition(arr, left, right); quickSort(arr, left, pivot_index - 1); quickSort(arr, pivot_index + 1, right); } } public static void main(String[] args) { int[] arr2 = {1,0,-1}; quickSort(arr2); for (int i : arr2) { System.out.print(i + " "); } } }
不解释了,直接参考上面给出的参考链接即可。