标签:
快速排序是基于分治策略的一个排序算法。其基本思想是,对于输入的字数组a[p:r],
按以下3个步骤进行排序:
1、分解(divide):以a[p]为基准元素将a[p:r]划分成3段a[p:q-1],a[q],a[q+1:r],使得a[p:q-1]中任何元素小于等于a[q],a[q+1:r]中任何元素大于等于a[q]。下标q在划分过程中确定。
2、递归求解(conquer):通过递归调用快速排序算法,分别对a[p:q-1]和a[q+1:r]进行排序。
3、合并(merge):由于对a[p:q-1]和a[q+1:r]的排序是就地进行的,所以在a[p:q-1]和a[q+1:r]都已经排好序后不需要执行任何计算,a[p:r]就已经排好序。(其实就是对数组进行分解之后,a[q]就是最终数组的a[q],也就是说每一次分解都会确定有序数组中的一个元素,一直递归直至最后只剩一个元素就不需要再分解,这个元素就是最终结果)。
1 public class QuickSort { 2 3 public static int a[]= {1,4,3,8,6,0,2,5}; 4 5 public static void qSort(int p,int r){ 6 if(p<r){ 7 int q = partition(p,r); //a[q]是最后排序的结果 8 qSort(p,q-1); //对左半段排序 9 qSort(q+1,r); //对右半段排序 10 } 11 } 12 13 private static int partition(int p, int r) { 14 int i=p, 15 j=r+1; 16 int x=a[p]; 17 //将小于x的元素交换到左边区域 18 //将大于x的元素交换到右边区域 19 while(true){ 20 while(a[++i]<x&&i<r) ; //++i,所以是对[p+1,r]排序,最后要将p插进来 21 while(a[--j]>x) ; 22 if(i>=j) break; 23 swap(a,i,j); 24 } 25 /* 26 * a[j]之所以和a[p]交换,而不是和a[i]交换,是因为上面的循环结束后,a[j]<=a[p]<=a[i] 27 * 而p是第一个元素(即是分组后的左半部分(小于等于p的部分)) 28 */ 29 a[p]=a[j]; 30 a[j]=x; 31 return j; 32 } 33 34 private static void swap(int[] a, int i, int j) { 35 int temp=a[i]; 36 a[i] = a[j]; 37 a[j] = temp; 38 } 39 40 public static void main(String[] args) { 41 qSort(0,a.length-1); 42 for(int i=0;i<a.length;i++) 43 System.out.print(a[i]+" "); 44 } 45 46 }
其实之前一直不明白partition最后为什么要将a[j]与a[p]的值交换,后来才想明白,因为partition是以a[p]为基准分两组的,
最后的结果中左半部分小于等于a[p],右半部分大于等于a[p],
也就是说,最后的有序数组中,a[p]是位于左右半部分中间的,所以将a[p]插入到他们中间,
之所以选择j而不是i的原因是:while(true)循环之后,a[j]<=a[p]<=a[i],而a[p]是整个数组的第一个元素(左半部分),
所以交换后仍然能保证左半部分比a[p]小,右半部分比a[p]大。
标签:
原文地址:http://www.cnblogs.com/eleven24/p/4243850.html