java.util.Arrays提供了对数组int[] long[] byte[] char[] short[] double[] float[] Object[]的排序算法Arrays.sort(T[]),以及更高级的Arrays.sort(T[], Comparator<? super T> c);
先看对int\long\byte\char\short的排序算法sort1(byte x[], int off, int len)
1)排序长度len<7时,直接采用插入排序,是因为虽然复杂度为O(n^2),但是由于个数较少,插入排序可以省掉快排递归需要的时间,效率较高;
1 // Insertion sort on smallest arrays 2 if (len < 7) { 3 for (int i=off; i<len+off; i++) 4 for (int j=i; j>off && x[j-1]>x[j]; j--) 5 swap(x, j, j-1); 6 return; 7 }
2)len>=7时,采用快排递归进行排序;为了优化效率,需要选取较好的比较值来把排序数组尽量分为长度相近的两部分;选择比较值的方法如下:
3)len==7时,取中点的值为比较值:
1 int m = off + (len >> 1);
4)len>7 && len<=40时,取头、尾、中点三个值的中间值为比较值:
1 if (len > 7) { 2 int l = off; 3 int n = off + len - 1; 4 m = med3(x, l, m, n); // Mid-size, med of 3 5 }
其中med3为取中间值:
1 /** 2 * Returns the index of the median of the three indexed bytes. 3 */ 4 private static int med3(byte x[], int a, int b, int c) { 5 return (x[a] < x[b] ? 6 (x[b] < x[c] ? b : x[a] < x[c] ? c : a) : 7 (x[b] > x[c] ? b : x[a] > x[c] ? c : a)); 8 }
5)len>40时,将数组8等分得到9个点,分三组取中间值之后将三个中间值的中间值作为比较值:
1 if (len > 40) { // Big arrays, pseudomedian of 9 2 int s = len/8; 3 l = med3(x, l, l+s, l+2*s); 4 m = med3(x, m-s, m, m+s); 5 n = med3(x, n-2*s, n-s, n); 6 } 7 m = med3(x, l, m, n); // Mid-size, med of 3
6)随后对数组进行快排,其中优化的部分是将与比较值相等的值放到数组头和尾,随后进行swap将这些相等的值放到比较值所在相同的位置,这样比快排要省一些比较时间;
1 byte v = x[m]; 2 3 // Establish Invariant: v* (<v)* (>v)* v* 4 int a = off, b = a, c = off + len - 1, d = c; 5 while(true) { 6 while (b <= c && x[b] <= v) { 7 if (x[b] == v) 8 swap(x, a++, b); 9 b++; 10 } 11 while (c >= b && x[c] >= v) { 12 if (x[c] == v) 13 swap(x, c, d--); 14 c--; 15 } 16 if (b > c) 17 break; 18 swap(x, b++, c--); 19 } 20 21 // Swap partition elements back to middle 22 int s, n = off + len; 23 s = Math.min(a-off, b-a ); vecswap(x, off, b-s, s); 24 s = Math.min(d-c, n-d-1); vecswap(x, b, n-s, s); 25 26 // Recursively sort non-partition-elements 27 if ((s = b-a) > 1) 28 sort1(x, off, s); 29 if ((s = d-c) > 1) 30 sort1(x, n-s, s);
其中vecswap是一个按顺序拷贝
1 /** 2 * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)]. 3 */ 4 private static void vecswap(byte x[], int a, int b, int n) { 5 for (int i=0; i<n; i++, a++, b++) 6 swap(x, a, b); 7 }
sort1对5种基本类型的排序到此结束,主要是采用了优化后的快排。
对double\float的排序是sort2(double a[], int fromIndex, int toIndex)
先看代码:
1 private static void sort2(double a[], int fromIndex, int toIndex) { 2 final long NEG_ZERO_BITS = Double.doubleToLongBits(-0.0d); 3 /* 4 * The sort is done in three phases to avoid the expense of using 5 * NaN and -0.0 aware comparisons during the main sort. 6 */ 7 8 /* 9 * Preprocessing phase: Move any NaN‘s to end of array, count the 10 * number of -0.0‘s, and turn them into 0.0‘s. 11 */ 12 int numNegZeros = 0; 13 int i = fromIndex, n = toIndex; 14 while(i < n) { 15 if (a[i] != a[i]) { 16 double swap = a[i]; 17 a[i] = a[--n]; 18 a[n] = swap; 19 } else { 20 if (a[i]==0 && Double.doubleToLongBits(a[i])==NEG_ZERO_BITS) { 21 a[i] = 0.0d; 22 numNegZeros++; 23 } 24 i++; 25 } 26 } 27 28 // Main sort phase: quicksort everything but the NaN‘s 29 sort1(a, fromIndex, n-fromIndex); 30 31 // Postprocessing phase: change 0.0‘s to -0.0‘s as required 32 if (numNegZeros != 0) { 33 int j = binarySearch0(a, fromIndex, n, 0.0d); // posn of ANY zero 34 do { 35 j--; 36 } while (j>=0 && a[j]==0.0d); 37 38 // j is now one less than the index of the FIRST zero 39 for (int k=0; k<numNegZeros; k++) 40 a[++j] = -0.0d; 41 } 42 }
核心思想仍然是采用优化后的快排(29行sort1),但对double和float的性质做了一些修改;
由于double中0和-0.0d并不相等,因此在12-26行将等于0和NaN的值放在数组尾部不参与排序;注意15行a[i]!=a[i]是检验double/float中NaN的常用方式,当d是NaN时,d==d为false,而d!=d为true;
随后对非0值的数组进行优化后的快排,32-41行将未参与排序的值放入排序后的队尾;
对Object[]的排序sort(Object[] a)
与上述基本类型不同,对对象数组进行排序采用的是mergeSort,原因是mergeSort稳定性比快排好,Object中除了排序项以外存在其他成员,因此对稳定性要求高;
1 /** 2 * Src is the source array that starts at index 0 3 * Dest is the (possibly larger) array destination with a possible offset 4 * low is the index in dest to start sorting 5 * high is the end index in dest to end sorting 6 * off is the offset to generate corresponding low, high in src 7 */ 8 private static void mergeSort(Object[] src, 9 Object[] dest, 10 int low, 11 int high, 12 int off) { 13 int length = high - low; 14 15 // Insertion sort on smallest arrays 16 if (length < INSERTIONSORT_THRESHOLD) { 17 for (int i=low; i<high; i++) 18 for (int j=i; j>low && 19 ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--) 20 swap(dest, j, j-1); 21 return; 22 } 23 24 // Recursively sort halves of dest into src 25 int destLow = low; 26 int destHigh = high; 27 low += off; 28 high += off; 29 int mid = (low + high) >>> 1; 30 mergeSort(dest, src, low, mid, -off); 31 mergeSort(dest, src, mid, high, -off); 32 33 // If list is already sorted, just copy from src to dest. This is an 34 // optimization that results in faster sorts for nearly ordered lists. 35 if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) { 36 System.arraycopy(src, low, dest, destLow, length); 37 return; 38 } 39 40 // Merge sorted halves (now in src) into dest 41 for(int i = destLow, p = low, q = mid; i < destHigh; i++) { 42 if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0) 43 dest[i] = src[p++]; 44 else 45 dest[i] = src[q++]; 46 } 47 }
当元素个数少于7时,仍然采用插入排序,多于7时采用递归的mergeSort;
若自己 实现了Comparator<? super T>,则上述算法的Comparable采用c比较即可;
thanks to
http://www.cnblogs.com/gw811/archive/2012/10/04/2711746.html