Array.sort详解(jdk6)

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 - 14         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

 

转载于:https://www.cnblogs.com/ibuki/p/4829145.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值