6版本以下用插入和归并判断的
7版本object的排序依然用的归并排序,int和其他基本类型用的改进的插入排序双轴快速排序和归并排序,但归并排序已经被注释即将过时.
java8以上数组元素个数<47用的插入排序,大于47小于286用的双轴快速插入,大于286后做判断,判断原则是以已经分成若干子区域的数组的无序程度,如果无序程度大于67,依然使用双轴快速排序,小于67使用归并排序.
First, Arrays.sort(int[] a) analysis
Summarize the Arrays.sort(int[] a) method:
- Array length 0-47: Strip
- Array length 47-286: Dual-Pivot fast row
- Array length >286
- The array is basically ordered: merge
- Array out of order: Dual-Pivot fast row
Arrays.sort has a number of overloaded methods. Here we look at the Arrays.sort(int[] a) method. Other methods are similar.
Public static void sort(int[] a) {
DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
You can see that the Sort method of the DualPivotQuicksort class is called. The DualPivotQuicksort is a quick sort. The students who want to know can read these two articles and explain them very thoroughly:
Two-axis fast sorting - implementation principle
Why is DualPivotQuicksort better than regular fast row?
Let’s take a look at the DualPivotQuicksort.sort method:
Static void sort(int[] a, int left, int right,
Int[] work, int workBase, int workLen) {
/**
* When the array length to be sorted is less than QUICKSORT_THRESHOLD=286:
* Call sort(a, left, right, true); simply say this method:
* When the array length is less than INSERTION_SORT_THRESHOLD=47, use the strip,
* Use the DualPivotQuicksort dual-axis quick release between 47-286.
*/
If (right - left < QUICKSORT_THRESHOLD) {
Sort(a, left, right, true);
Return;
}
Int[] run = new int[MAX_RUN_COUNT + 1];
Int count = 0;
Run[0] = left;
/**
* At this point, the array length is >286. If the array is basically ordered, it is to use the two-axis fast row, otherwise use the merge sort
*
*
* The mechanism for judging whether an array has been basically ordered is:
*
* Divide the array into several sub-blocks that are incremented or decremented, and store the demarcation points of each block in the run array, for example:
*
* Array arr = {9, 6, 6, 4, 8, 20, 18, 17, 16, 15}
* Can be divided into three blocks
* {9, 6, 6, 4} {8, 20} {18, 17, 16, 15}
*
* The corresponding run array is
* {0, 4, 6, 10, 0, 0, 0, 0,...},
* indicates that arr[0]-arr[4-1] is the first block,
* indicates that arr[4]-arr[6-1] is the second block.
* indicates that arr[6]-arr[10-1] is the third block.
*
* If the block in the array exceeds MAX_RUN_COUNT=67, the array is out of order, and use Dual-Pivot to queue up.
* Conversely indicates that the order is high, and the merge sort is used at this time.
*/
For (int k = left; k < right; run[count] = k) {
// Equal items in the beginning of the sequence
While (k < right && a[k] == a[k + 1])
k++;
/**
* indicates that the array is already in an ordered state. count=0
*/
If (k == right) break; // Sequence finishes with equal items
If (a[k] < a[k + 1]) { // ascending
/**
* Find the boundaries of sequential blocks
*/
While (++k <= right && a[k - 1] <= a[k]) ;
} else if (a[k] > a[k + 1]) { // descending
/**
* Find the boundary of the reverse block
*/
While (++k <= right && a[k - 1] >= a[k]) ;
/**
* Adjust the reverse block to make it a sequential block
*/
For (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
Int t = a[lo];
a[lo] = a[hi];
a[hi] = t;
}
}
/**
* When a reverse block is adjusted to a sequential state, it is compared with the adjacent adjacent block,
* See if the last element of the last sequential block (which is also the largest one) is smaller than the first element of the current sequential block (which is also the smallest element)
* If befor.last <= this.first Description These two blocks can be merged together to form a sequential block, at which point count--, eliminates a reverse block
*/
If (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
Count--;
}
/**
* When the array is already basically ordered, use the fast row
*/
If (++count == MAX_RUN_COUNT) {
Sort(a, left, right, true);
Return;
}
}
/**
* count == 0 means the array is already in sequential state
*/
If (count == 0) {
Return;
} else if (count == 1 && run[count] > right) {
Return;
}
Right++;
If (run[count] < right) {
Run[++count] = right;
}
/**
* The following is the use of merge sorting
*/
Byte odd = 0;
For (int n = 1; (n <<= 1) < count; odd ^= 1) ;
/ / Create a temporary array b used to merge
Int[] b; // temp array; alternates with a
Int ao, bo; // array offsets from 'left'
Int blen = right - left; // space needed for b
If (work == null || workLen < blen || workBase + blen > work.length) {
Work = new int[blen];
workBase = 0;
}
If (odd == 0) {
System.arraycopy(a, left, work, workBase, blen);
b = a;
Bo = 0;
a = work;
Ao = workBase - left;
} else {
b = work;
Ao = 0;
Bo = workBase - left;
}
// merge, complete condition: reverse order count=1
For (int last; count > 1; count = last) {
For (int k = (last = 0) + 2; k <= count; k += 2) {
Int hi = run[k], mi = run[k - 1];
For (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
If (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
b[i + bo] = a[p++ + ao];
} else {
b[i + bo] = a[q++ + ao];
}
}
Run[++last] = hi;
}
//If the number of subsequences is an odd number, the two will be merged one after the other, and this part will be copied to b.
If ((count & 1) != 0) {
For (int i = right, lo = run[count - 1]; --i >= lo;
发送反馈
历史记录