java arrays.sort排序_Java下的Arrays排序sort算法源码解析(下)

知识回顾

在上一章节中,我们介绍了关于Java下的Arrays排序sort算法的数组长度不超过QUICKSORT_THRESHOLD数值为286时的算法应用,分别有插入排序,双轴快排,单轴快排和结对插入排序。Java下的Arrays排序sort算法源码解析(上)。今天我们来探索另外一种情况。

探索开始

我们先附上下一段的源码来进行分析:

/*

* Index run[i] is the start of i-th run

* (ascending or descending sequence).

*/

int[] run = new int[MAX_RUN_COUNT + 1];

int count = 0; run[0] = left;

// Check if the array is nearly sorted

for (int k = left; k < right; run[count] = k) {

if (a[k] < a[k + 1]) { // ascending

while (++k <= right && a[k - 1] <= a[k]);

} else if (a[k] > a[k + 1]) { // descending

while (++k <= right && a[k - 1] >= a[k]);

for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {

int t = a[lo]; a[lo] = a[hi]; a[hi] = t;

}

} else { // equal

for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {

if (--m == 0) {

sort(a, left, right, true);

return;

}

}

}

/*

* The array is not highly structured,

* use Quicksort instead of merge sort.

*/

if (++count == MAX_RUN_COUNT) {

sort(a, left, right, true);

return;

}

}

这里乍一看会感觉毫无逻辑,这里用的是什么算法,但是我们细细慢慢琢磨,我们可以发现一定的规则:

首先这个算法是针对于数组有序性比较好的情况来进行的,它刚开始会从头到尾遍历整个数组,并且如果有序性较好,他会直接扫描通过,速度很快。

这里有一个情况是,如果这里相同的值非常多的时候,并且是连在一起的,这里设置了一个阈值MAX_RUN_LENGTH数值为33,当达到这个值,我们就会使用在上一章那里的逻辑进行排序。

最后还有最重要的逻辑,这里会有一个count值可能会让大家费解,这个值的作用也是设置一个阈值,不过针对的作用是当有序性断连的次数达到MAX_RUN_COUNT数值为67时,认为这个数组无序程度比较高,就不会再继续使用这个算法了,而会使用之前上章介绍的快排,如果有序则使用归并排序算法

OK,上面那个算法逻辑也比较简单,没有什么特殊点,我们继续向下。

// Check special cases

// Implementation note: variable "right" is increased by 1.

if (run[count] == right++) { // The last run contains one element

run[++count] = right;

} else if (count == 1) { // The array is already sorted

return;

}

// Determine alternation base for merge

byte odd = 0;

for (int n = 1; (n <<= 1) < count; odd ^= 1);

// Use or create temporary array b for merging

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;

}

// Merging

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 ((count & 1) != 0) {

for (int i = right, lo = run[count - 1]; --i >= lo;

b[i + bo] = a[i + ao]

);

run[++last] = right;

}

int[] t = a; a = b; b = t;

int o = ao; ao = bo; bo = o;

}

如果到这了,就说明开始了归并排序,不过这里的归并排序我看的并不是很懂,硬看有点头大,想了下还是算了,找了个简单的归并算法看了下理解了起逻辑。

今日总结

今天我们补全了关于Arrays的sort方法设下部分,总结而言为了优化数组的排序速度,在编写方法时使用了很多策略来提升性能,阅读这一段,让我更加加深了对于排序算法的理解,这波不亏~~~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值