栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java快排源码简单解读

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java快排源码简单解读


前言

今天下午的时候有同学跟我聊快排的效率,我试着讲一遍底层实现发现印象已经模糊了。
所以刚才上课摸鱼对sort源码重新看了一遍,写了一点注释,顺便分享给大家,有不对的地方望指正。
电脑电量原因,经典的归并实现部分没有写


Java快排源码

java.util.Arrays.sort()调用的java.util.DualPivotQuickSort.sort()
所以这篇文章解释的是java.util.DualPivotQuickSort.sort()的实现

static void sort(int[] a, int left, int right,
                 int[] work, int workbase, int workLen) {
    // Use Quicksort on small arrays
    //小于47使用插入排序,47~286使用快排
    if (right - left < QUICKSORT_THRESHOLD) {
        sort(a, left, right, true);
        return;
    }
	
    //以下为大于286的排序
    
    //定义一个记录第i次运行起始位置的数组
    int[] run = new int[MAX_RUN_COUNT + 1];
    //count记录每一段降序,初始为第0段,第0段起始位置为left
    int count = 0; run[0] = left;

    // Check if the array is nearly sorted
    //从left~right的遍历
    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++;
        if (k == right) break;  // Sequence finishes with equal items
        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]);
            // Transform into an ascending sequence
            //将这一条降序序列进行翻转
            for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
                int t = a[lo]; a[lo] = a[hi]; a[hi] = t;
            }
        }

        // Merge a transformed descending sequence followed by an
        // ascending sequence
        //将转换后的降序,与前面的升序连接
        //升序序列+转换后的降序序列,count向前找这段序列中出现降序的地方
        if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
            count--;
        }

        
        
        if (++count == MAX_RUN_COUNT) {
            sort(a, left, right, true);
            return;
        }
    }

    // These invariants should hold true:
    //    run[0] = 0
    //    run[] = right + 1; (terminator)

    if (count == 0) {
        //如果没有降序,这是一个单调的,直接返回
        // A single equal run
        return;
    } else if (count == 1 && run[count] > right) {
        //如果有降序,但降序起始位置在范围之外
        // Either a single ascending or a transformed descending run.
        // Always check that a final run is a proper terminator, otherwise
        // we have an unterminated trailing run, to handle downstream.
        return;
    }
    right++;
    if (run[count] < right) {
        //极端情况:最后一次运行的位置不在终点
        //这可能是由于最后一段序列是相等序列,或者是有一个单元素在末尾
        //Fix方法:run[count+1]=right;
        
        // Corner case: the final run is not a terminator. This may happen
        // if a final run is an equals run, or there is a single-element run
        // at the end. Fix up by adding a proper terminator at the end.
        // Note that we terminate with (right + 1), incremented earlier.
        run[++count] = right;
    }

    // Determine alternation base for merge
    //odd确定合并的替代基础
    byte odd = 0;
    for (int n = 1; (n <<= 1) < count; odd ^= 1);

    //准备一个临时空间
    //排序过程中可用的额外空间为work中的[workbase,workbase+workLen]。如果work给定的空间不够用,就会新开辟足够的空间。
    //a为原数组,b为临时数组,与a交替使用
    // 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;
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/785918.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号