java.util.Arrays类。这个类是个数组工具类。主要提供方法sort(),fill(),binarySearch(),还有数组复制等方法。打开源文件,刚超过4千行,不过包括很多注释,那么我在这里主要讲讲这里面涉及的排序算法和查找算法。
一、binarySearch()方法,二分法查找算法, 算法思想:当数据量很大适宜采用该方法。采用二分法查找时,数据需是排好序的。 基本思想:假设数据是按升序排序的,对于给定值x,从序列的中间位置开始比较,如果当前位置值等于x,则查找成功;若x小于当前位置值,则在数列的前半段 中查找;若x大于当前位置值则在数列的后半段中继续查找,直到找到为止。
- //针对int类型数组的二分法查找,key为要查找数的下标
- private static int binarySearch0(int[] a, int fromIndex, int toIndex,
- int key) {
- int low = fromIndex;
- int high = toIndex - 1;
- while (low <= high) {
- int mid = (low + high) >>> 1;//无符号左移一位,相当于除以二
- int midVal = a[mid];
- if (midVal < key)
- low = mid + 1;
- else if (midVal > key)
- high = mid - 1;
- else
- return mid; // key found
- }
- return -(low + 1); // key not found.
- }
二、sort()方法针对引用类型数组采取的算法是归并排序。算法思想:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
- private static final int INSERTIONSORT_THRESHOLD = 7;//插入排序门槛
- public static void sort(Object[] a) {
- Object[] aux = (Object[])a.clone();
- mergeSort(aux, a, 0, a.length, 0);
- }
- //归并排序
- private static void mergeSort(Object[] src,
- Object[] dest,
- int low,
- int high,
- int off) {
- int length = high - low;
- if (length < INSERTIONSORT_THRESHOLD) { //若数组长度小于7,则用冒泡排序
- for (int i=low; i<high; i++)
- for (int j=i; j>low &&
- ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
- swap(dest, j, j-1);
- return;
- }
- // Recursively sort halves of dest into src
- int destLow = low;
- int destHigh = high;
- low += off;
- high += off;
- int mid = (low + high) >>> 1; //无符号左移一位,
- mergeSort(dest, src, low, mid, -off);
- mergeSort(dest, src, mid, high, -off);
- // If list is already sorted, just copy from src to dest. This is an
- // optimization that results in faster sorts for nearly ordered lists.
- if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
- System.arraycopy(src, low, dest, destLow, length);
- return;
- }
- // Merge sorted halves (now in src) into dest
- for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
- if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
- dest[i] = src[p++];
- else
- dest[i] = src[q++];
- }
- }
三、sort()方法采取的是快速排序算法,算法思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
- /**
- * Swaps x[a] with x[b].
- */
- private static void swap(int x[], int a, int b) {
- int t = x[a];
- x[a] = x[b];
- x[b] = t;
- }
- public static void sort(int[] a) {
- sort1(a, 0, a.length);
- }
- private static int med3(int x[], int a, int b, int c) {//找出三个中的中间值
- return (x[a] < x[b] ?
- (x[b] < x[c] ? b : x[a] < x[c] ? c : a) :
- (x[b] > x[c] ? b : x[a] > x[c] ? c : a));
- }
- /**
- * Sorts the specified sub-array of integers into ascending order.
- */
- private static void sort1(int x[], int off, int len) {
- // Insertion sort on smallest arrays
- if (len < 7) {//采用冒泡排序
- for (int i=off; i<len+off; i++)
- for (int j=i; j>off && x[j-1]>x[j]; j--)
- swap(x, j, j-1);
- return;
- }
- //采用快速排序
- // Choose a partition element, v
- int m = off + (len >> 1); // Small arrays, middle element
- if (len > 7) {
- int l = off;
- int n = off + len - 1;
- if (len > 40) { // Big arrays, pseudomedian of 9
- int s = len/8;
- l = med3(x, l, l+s, l+2*s);
- m = med3(x, m-s, m, m+s);
- n = med3(x, n-2*s, n-s, n);
- }
- m = med3(x, l, m, n); // Mid-size, med of 3
- }
- int v = x[m];
- // Establish Invariant: v* (<v)* (>v)* v*
- int a = off, b = a, c = off + len - 1, d = c;
- while(true) {
- while (b <= c && x[b] <= v) {
- if (x[b] == v)
- swap(x, a++, b);
- b++;
- }
- while (c >= b && x[c] >= v) {
- if (x[c] == v)
- swap(x, c, d--);
- c--;
- }
- if (b > c)
- break;
- swap(x, b++, c--);
- }
- // Swap partition elements back to middle
- int s, n = off + len;
- s = Math.min(a-off, b-a ); vecswap(x, off, b-s, s);
- s = Math.min(d-c, n-d-1); vecswap(x, b, n-s, s);
- // Recursively sort non-partition-elements
- if ((s = b-a) > 1)
- sort1(x, off, s);
- if ((s = d-c) > 1)
- sort1(x, n-s, s);
- }
四、针对double,float类型数组排序的sort()方法,采取了先把所有的数组元素值为-0.0d的转换成0.0d,再利用快速排序排好序,最后再还原。
- public static long doubleToRawLongBits(double value)根据 IEEE 754 浮点“双精度格式”位布局,返回指定浮点值的表示形式,并保留 NaN 值。
- 第 63 位(掩码 0x8000000000000000L 选定的位)表示浮点数的符号。第 62-52 位(掩码 0x7ff0000000000000L 选定的位)表示指数。第 51-0 位(掩码 0x000fffffffffffffL 选定的位)表示浮点数的有效数字(有时也称为尾数)。
- 如果参数是正无穷大,则结果为 0x7ff0000000000000L。
- 如果参数是负无穷大,则结果为 0xfff0000000000000L。
- 如果参数是 NaN,则结果是表示实际 NaN 值的 long 整数。与 doubleToLongBits 方法不同,doubleToRawLongBits 并没有压缩那些将 NaN 编码为一个“规范的”NaN 值的所有位模式。
- 在所有情况下,结果都是一个 long 整数,将其赋予 longBitsToDouble(long) 方法将生成一个与 doubleToRawLongBits 的参数相同的浮点值。
- 参数:
- value - 双精度 (double) 浮点数。
下面是源代码中的方法:
- public static void sort(double[] a) {
- sort2(a, 0, a.length);
- }
- private static void sort2(double a[], int fromIndex, int toIndex) {
- //static long doubleToLongBits(double value)
- //根据 IEEE 754 浮点双精度格式 ("double format") 位布局,返回指定浮点值的表示形式。
- final long NEG_ZERO_BITS = Double.doubleToLongBits(-0.0d);
- /*
- * The sort is done in three phases to avoid the expense of using
- * NaN and -0.0 aware comparisons during the main sort.
- */
- /*
- * Preprocessing phase: Move any NaN's to end of array, count the
- * number of -0.0's, and turn them into 0.0's.
- */
- int numNegZeros = 0;
- int i = fromIndex, n = toIndex;
- while(i < n) {
- if (a[i] != a[i]) { //这段搞不懂,源代码怪怪的,感觉多此一举
- ouble swap = a[i];
- a[i] = a[--n];
- a[n] = swap;
- } else {
- if (a[i]==0 && Double.doubleToLongBits(a[i])==NEG_ZERO_BITS) {
- a[i] = 0.0d;
- numNegZeros++;
- }
- i++;
- }
- }
- // Main sort phase: quicksort everything but the NaN's
- sort1(a, fromIndex, n-fromIndex);
- // Postprocessing phase: change 0.0's to -0.0's as required
- if (numNegZeros != 0) {
- int j = binarySearch0(a, fromIndex, n, 0.0d); // posn of ANY zero
- do {
- j--;
- } while (j>=0 && a[j]==0.0d);
- // j is now one less than the index of the FIRST zero
- for (int k=0; k<numNegZeros; k++)
- a[++j] = -0.0d;
- }
- }
http://zengzhaoshuai.iteye.com/blog/1130376
http://hxraid.iteye.com/blog/665095/