java Arrays.sort 源码分析
2012-06-05 22:05
417 查看
java Arrays 类中的sort排序提供了对基本类型(int、long、short)和对象类型的排序。基本类型的排序采用的是调优的
快速排序。对象的排序采用的是改进的归并排序。下面将分别介绍这两种排序方式。
源码中的快速排序,主要做了以下几个方面的优化:
1)当待排序的数组中的元素个数较少时,源码中的阀值为7,采用的是插入排序。尽管插入排序的时间复杂度为0(n^2),但是当数组元素较少时,插入排序 优于快速排序,因为这时快速排序的递归操作影响性能。
2)较好的选择了划分元。能够将数组分成大致两个相等的部分,避免出现最坏的情况。例如当数组有序的的情况下,选择第一个元素作为划分元,将使得算法的时间复杂度达到O(n^2).
源码中选择划分元的方法:
当数组大小 为size<=7时 ,取数组中间元素作为划分元。
当数组大小 7<size<=40时,取首、中、末 三个元素中间大小的元素作为划分元。
当数组大小 size>40 时 ,从待排数组中较均匀的选择9个元素,选出一个伪中数做为划分元。
3)根据划分元 v ,形成不变式 v* (<v)* (>v)* v*
普通的快速排序算法,经过一次划分后,将划分元排到素组较中间的位置,左边的元素小于划分元,右边的元素大于划分元,而没有将与划分元相等的元素放在其附近,这一点,在Arrays.sort()中得到了较大的优化。
举例:15、93、15、41、6、15、22、7、15、20
因 7<size<=40,所以在15、6、和20 中选择v = 15 作为划分元。
经过一次换分后: 15、15、7、6、41、20、22、93、15、15. 与划分元相等的元素都移到了素组的两边。
接下来将与划分元相等的元素移到数组中间来,形成:7、6、15、15、15、15、41、20、22、93.
最后递归对两个区间进行排序[7、6]和[41、20、22、93].
部分源码:
public class Arrays {
/**
* Sorts the specified array of ints into ascending numerical order.
* The sorting algorithm is a tuned quicksort, adapted from Jon
* L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
* Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
* 1993). This algorithm offers n*log(n) performance on many data sets
* that cause other quicksorts to degrade to quadratic performance.
*
* @param a the array to be sorted
*/
public static void sort(int a[]){
sort1(a,0,a.length);
}
//对指定范围的数组按升序排序,从fromIndex 到 toIndex
public static void sort(int[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex); // 检查待排数组的范围是否合法。
sort1(a, fromIndex, toIndex-fromIndex);
}
/**
* 对指定的整形子数组进行升序排序。
*/
private static void sort1(int x[], int off, int len) {
//小数组时采用插入排序
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); // size=7 时 取中间元素作为划分元
if (len > 7) { // 7<size<=40 取首中末中的中间大小的元素作为划分元
int l = off;
int n = off + len - 1;
if (len > 40) { // 从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); //取出中间大小的元素的位置。
}
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--);
1 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);
}
/**
* 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;
}
/**
* Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
*/
private static void vecswap(int x[], int a, int b, int n) {
for (int i=0; i<n; i++, a++, b++)
swap(x, a, b);
}
/**
* Returns the index of the median of the three indexed integers.
*/
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 array of objects into ascending order, according to
* the {@linkplain Comparable natural ordering}
* of its elements. All elements in the array
* must implement the {@link Comparable} interface. Furthermore, all
* elements in the array must be <i>mutually comparable</i> (that is,
* <tt>e1.compareTo(e2)</tt> must not throw a <tt>ClassCastException</tt>
* for any elements <tt>e1</tt> and <tt>e2</tt> in the array).<p>
*
* This sort is guaranteed to be <i>stable</i>: equal elements will
* not be reordered as a result of the sort.<p>
*
* The sorting algorithm is a modified mergesort (in which the merge is
* omitted if the highest element in the low sublist is less than the
* lowest element in the high sublist). This algorithm offers guaranteed
* n*log(n) performance.
*
* @param a the array to be sorted
* @throws ClassCastException if the array contains elements that are not
* <i>mutually comparable</i> (for example, strings and integers).
*/
//对对象进行排序。
public static void sort(Object[] a) {
Object[] aux = (Object[])a.clone();
mergeSort(aux, a, 0, a.length, 0);
}
//对数组中指定范围的对象进行排序
public static void sort(Object[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
Object[] aux = copyOfRange(a, fromIndex, toIndex);
mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
}
private static final int INSERTIONSORT_THRESHOLD = 7;//调优参数
/**
* 将指定范围的对象数组按自然顺序升序排序。
* src[] 原待排数组
* dest[] 目的待排数组
* low 待排数组的下界位置
* high 待排数组的上界位置
* off 从数组的第off个元素开始排序
*/
private static void mergeSort(Object[] src,
Object[] dest,
int low,
int high,
int off) {
int length = high - low;
// Insertion sort on smallest arrays
if (length < INSERTIONSORT_THRESHOLD) {
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.
// 如果列表已经排好序了,只要将src 拷贝到dest。这对接近已排序的列表做了优化。
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++];
}
}
/**
* Swaps x[a] with x[b].
*/
private static void swap(Object[] x, int a, int b) {
Object t = x[a];
x[a] = x[b];
x[b] = t;
}
}
快速排序。对象的排序采用的是改进的归并排序。下面将分别介绍这两种排序方式。
源码中的快速排序,主要做了以下几个方面的优化:
1)当待排序的数组中的元素个数较少时,源码中的阀值为7,采用的是插入排序。尽管插入排序的时间复杂度为0(n^2),但是当数组元素较少时,插入排序 优于快速排序,因为这时快速排序的递归操作影响性能。
2)较好的选择了划分元。能够将数组分成大致两个相等的部分,避免出现最坏的情况。例如当数组有序的的情况下,选择第一个元素作为划分元,将使得算法的时间复杂度达到O(n^2).
源码中选择划分元的方法:
当数组大小 为size<=7时 ,取数组中间元素作为划分元。
当数组大小 7<size<=40时,取首、中、末 三个元素中间大小的元素作为划分元。
当数组大小 size>40 时 ,从待排数组中较均匀的选择9个元素,选出一个伪中数做为划分元。
3)根据划分元 v ,形成不变式 v* (<v)* (>v)* v*
普通的快速排序算法,经过一次划分后,将划分元排到素组较中间的位置,左边的元素小于划分元,右边的元素大于划分元,而没有将与划分元相等的元素放在其附近,这一点,在Arrays.sort()中得到了较大的优化。
举例:15、93、15、41、6、15、22、7、15、20
因 7<size<=40,所以在15、6、和20 中选择v = 15 作为划分元。
经过一次换分后: 15、15、7、6、41、20、22、93、15、15. 与划分元相等的元素都移到了素组的两边。
接下来将与划分元相等的元素移到数组中间来,形成:7、6、15、15、15、15、41、20、22、93.
最后递归对两个区间进行排序[7、6]和[41、20、22、93].
部分源码:
public class Arrays {
/**
* Sorts the specified array of ints into ascending numerical order.
* The sorting algorithm is a tuned quicksort, adapted from Jon
* L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
* Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
* 1993). This algorithm offers n*log(n) performance on many data sets
* that cause other quicksorts to degrade to quadratic performance.
*
* @param a the array to be sorted
*/
public static void sort(int a[]){
sort1(a,0,a.length);
}
//对指定范围的数组按升序排序,从fromIndex 到 toIndex
public static void sort(int[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex); // 检查待排数组的范围是否合法。
sort1(a, fromIndex, toIndex-fromIndex);
}
/**
* 对指定的整形子数组进行升序排序。
*/
private static void sort1(int x[], int off, int len) {
//小数组时采用插入排序
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); // size=7 时 取中间元素作为划分元
if (len > 7) { // 7<size<=40 取首中末中的中间大小的元素作为划分元
int l = off;
int n = off + len - 1;
if (len > 40) { // 从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); //取出中间大小的元素的位置。
}
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--);
1 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);
}
/**
* 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;
}
/**
* Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
*/
private static void vecswap(int x[], int a, int b, int n) {
for (int i=0; i<n; i++, a++, b++)
swap(x, a, b);
}
/**
* Returns the index of the median of the three indexed integers.
*/
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 array of objects into ascending order, according to
* the {@linkplain Comparable natural ordering}
* of its elements. All elements in the array
* must implement the {@link Comparable} interface. Furthermore, all
* elements in the array must be <i>mutually comparable</i> (that is,
* <tt>e1.compareTo(e2)</tt> must not throw a <tt>ClassCastException</tt>
* for any elements <tt>e1</tt> and <tt>e2</tt> in the array).<p>
*
* This sort is guaranteed to be <i>stable</i>: equal elements will
* not be reordered as a result of the sort.<p>
*
* The sorting algorithm is a modified mergesort (in which the merge is
* omitted if the highest element in the low sublist is less than the
* lowest element in the high sublist). This algorithm offers guaranteed
* n*log(n) performance.
*
* @param a the array to be sorted
* @throws ClassCastException if the array contains elements that are not
* <i>mutually comparable</i> (for example, strings and integers).
*/
//对对象进行排序。
public static void sort(Object[] a) {
Object[] aux = (Object[])a.clone();
mergeSort(aux, a, 0, a.length, 0);
}
//对数组中指定范围的对象进行排序
public static void sort(Object[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
Object[] aux = copyOfRange(a, fromIndex, toIndex);
mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
}
private static final int INSERTIONSORT_THRESHOLD = 7;//调优参数
/**
* 将指定范围的对象数组按自然顺序升序排序。
* src[] 原待排数组
* dest[] 目的待排数组
* low 待排数组的下界位置
* high 待排数组的上界位置
* off 从数组的第off个元素开始排序
*/
private static void mergeSort(Object[] src,
Object[] dest,
int low,
int high,
int off) {
int length = high - low;
// Insertion sort on smallest arrays
if (length < INSERTIONSORT_THRESHOLD) {
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.
// 如果列表已经排好序了,只要将src 拷贝到dest。这对接近已排序的列表做了优化。
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++];
}
}
/**
* Swaps x[a] with x[b].
*/
private static void swap(Object[] x, int a, int b) {
Object t = x[a];
x[a] = x[b];
x[b] = t;
}
}
相关文章推荐
- java源码分析:Arrays.sort
- Java中Arrays.sort排序源码分析
- java的Arrays.sort(Object[] a)方法源码分析
- java源码分析:Arrays.sort
- Java Collections Framework之Arrays(method:sort(),binarySearch(),copyOf())部分源码分析(基于JDK1.6)
- 【Java源码分析】Arrays.asList源码分析
- Java源码分析之Arrays
- java.util.Arrays.sort方法简单分析
- java Arrays.sort源码学习之旅(一)
- Arrays.sort()方法的源码分析
- java 集合中的Collections.sort()排序方法的源码分析(一)
- JAVA Arrays.sort()和Collectons.sort() 原理分析
- java 源码分析Arrays.asList方法详解
- Arrays类中sort源码分析
- java源码修炼(二) Stack源码分析
- 深度分析 Java 的 ClassLoader 机制(源码级别)(转)
- JAVA基础(三)String类源码分析
- Java集合:HashMap使用详解及源码分析
- Java Arrays.sort() on objects
- Java源码剖析—2 String源码分析