欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Arrays.sort(arr)是什么排序及代碼邏輯

 更新時(shí)間:2022年02月02日 09:55:36   作者:可樂(lè)加品客  
在學(xué)習(xí)過(guò)程中觀察到Arrays.sort(arr)算法可以直接進(jìn)行排序,但不清楚底層的代碼邏輯是什么樣子,今天通過(guò)本文給大家介紹下Arrays.sort(arr)是什么排序,感興趣的朋友一起看看吧

在學(xué)習(xí)過(guò)程中觀察到Arrays.sort(arr)算法可以直接進(jìn)行排序,但不清楚底層的代碼邏輯是什么樣子,記得自己之前在面試題里面也有面試官問(wèn)這個(gè)問(wèn)題,只能說(shuō)研究之后發(fā)現(xiàn)還是比較復(fù)雜的,并不是網(wǎng)上說(shuō)的快排或者二分插入之類(lèi)的。

首先看源碼:

 public static void sort(int[] a) {
        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
    }

它調(diào)用了DualPivotQuicksort的sort方法,乍一看以為是快排,這是很多網(wǎng)上的博主的說(shuō)法,繼續(xù)點(diǎn)開(kāi)向下看(代碼太長(zhǎng),沒(méi)耐心看可以直接跳過(guò)該段代碼QWQ):

 static void sort(int[] a, int left, int right,
                     int[] work, int workBase, int workLen) {
        // Use Quicksort on small arrays
        if (right - left < QUICKSORT_THRESHOLD) {
            sort(a, left, right, true);
            return;
        }
        /*
         * 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;
            }
        }
        // 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;
        }
    }

代碼很長(zhǎng),簡(jiǎn)要翻譯過(guò)來(lái),這里分了好幾種情況:

1.數(shù)組長(zhǎng)度小于286

這里又會(huì)調(diào)用一個(gè)sort方法,點(diǎn)開(kāi)該sort(),又會(huì)劃分情況:

數(shù)組長(zhǎng)度小于47,

當(dāng)leftmost(導(dǎo)入的一個(gè)布爾參數(shù))為true,則使用直接插入排序;

否則會(huì)調(diào)用另一種插入辦法,這里可以觀察到一個(gè)注釋:

/*
  * Every element from adjoining part plays the role
  * of sentinel, therefore this allows us to avoid the
  * left range check on each iteration. Moreover, we use
  * the more optimized algorithm, so called pair insertion
  * sort, which is faster (in the context of Quicksort)
  * than traditional implementation of insertion sort.
  */

大致意思是:相鄰部分的每個(gè)元素都扮演著哨兵的角色,因此這允許我們避免在每次迭代中進(jìn)行左范圍檢查。此外,我們使用了更優(yōu)化的算法,即所謂的成對(duì)插入排序,它比插入排序的傳統(tǒng)實(shí)現(xiàn)更快(在快速排序的上下文中)。

不過(guò)注意到,原函數(shù)參數(shù)傳參在這里leftmost為true,所以一定是直接插入排序,以上作為了解。

數(shù)組長(zhǎng)度大于47,采用一種快速排序的辦法,這里因?yàn)榇a太長(zhǎng),學(xué)藝不精,參考了一下http://www.dbjr.com.cn/article/236440.htm:

至于大過(guò)INSERTION_SORT_THRESHOLD(47)的,用一種快速排序的方法:

1.從數(shù)列中挑出五個(gè)元素,稱為 “基準(zhǔn)”(pivot);

2.重新排序數(shù)列,所有元素比基準(zhǔn)值小的擺放在基準(zhǔn)前面,所有元素比基準(zhǔn)值大的擺在基準(zhǔn)的后面(相同的數(shù)可以到任一邊)。在這個(gè)分區(qū)退出之后,該基準(zhǔn)就處于數(shù)列的中間位置。這個(gè)稱為分區(qū)(partition)操作;

3.遞歸地(recursive)把小于基準(zhǔn)值元素的子數(shù)列和大于基準(zhǔn)值元素的子數(shù)列排序。

當(dāng)數(shù)組長(zhǎng)度大于286時(shí)

此時(shí)回到那段很長(zhǎng)很長(zhǎng)的代碼段,在判斷小于286的長(zhǎng)度數(shù)組之后,從注解中:

// Check if the array is nearly sorted

這里是指檢查數(shù)組元素是不是快要排列好了,或者書(shū)面一點(diǎn)說(shuō),是不是有一定結(jié)構(gòu)了,然后看后面的for循環(huán),注意到一段代碼:

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

這里的sort和我們上面在數(shù)組長(zhǎng)度小于286時(shí)的那個(gè)sort方法是同一個(gè)方法,而針對(duì)這個(gè)count,是用來(lái)記錄逆序組的,打個(gè)比方:

此時(shí)有一個(gè)數(shù)組為1 5 6 9 8 7 2 3

當(dāng)數(shù)組認(rèn)定我們的順序應(yīng)該為升序時(shí),從第一個(gè)數(shù)開(kāi)始數(shù),此時(shí)9 8 7 2為降序,這就是逆序,將這四個(gè)數(shù)組合成一個(gè)組稱為逆序組,然后再?gòu)?開(kāi)始往后看。

當(dāng)統(tǒng)計(jì)到一個(gè)逆序組時(shí),count++,所以可以看出,count是用來(lái)記逆序組的,那么逆序組越多,這個(gè)結(jié)構(gòu)就越混亂

MAX_RUN_COUNT == 67 ,因此當(dāng)count一直加到67時(shí),就說(shuō)明已經(jīng)在一個(gè)混亂的臨界值了,此時(shí)執(zhí)行sort()方法

通過(guò)這一段分析,我們理一下思路:

?如果數(shù)組能運(yùn)行到這里,說(shuō)明數(shù)組的長(zhǎng)度大于等于286。符合該條件時(shí),我們要判斷這個(gè)數(shù)組是否有一定的結(jié)構(gòu):

(1)count<67,說(shuō)明不是那么混亂,有一定結(jié)構(gòu),跳過(guò);

(2)count>=67,說(shuō)明已經(jīng)混亂了,沒(méi)有結(jié)構(gòu),執(zhí)行sort方法,而已知數(shù)組長(zhǎng)度大于等于286,那么必然大于47,一定執(zhí)行快速排序。

跳過(guò)之后,經(jīng)過(guò)代碼的一大堆前置操作,最后看見(jiàn)下面的代碼里面一行注釋:

//Merging

顯然,這里后面用到歸并排序了,不詳細(xì)贅述。

好了,最后總結(jié):

  • 數(shù)組長(zhǎng)度小于286時(shí),根據(jù)數(shù)組長(zhǎng)度,分兩種情況:
    • 數(shù)組長(zhǎng)度小于47,使用直接插入排序
    • 數(shù)組長(zhǎng)度大于47,使用快速排序
  • 數(shù)組長(zhǎng)度大于286時(shí),根據(jù)數(shù)組排序情況,分兩種情況:
    • 數(shù)組內(nèi)順序較為混亂,即count逆序組數(shù)大于等于67,使用快速排序
    • 數(shù)組內(nèi)有一定順序,即count逆序組數(shù)小于67,使用歸并排序

參考資料:

《Java的Arrays.sort()方法到底用的什么排序算法》https://www.cnblogs.com/baichunyu/p/11935995.html作者:白春雨

到此這篇關(guān)于Arrays.sort(arr)是什么排序的文章就介紹到這了,更多相關(guān)Arrays.sort(arr)排序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java SpringBoot的相關(guān)知識(shí)點(diǎn)詳解

    Java SpringBoot的相關(guān)知識(shí)點(diǎn)詳解

    這篇文章主要介紹了SpringBoot的相關(guān)知識(shí)點(diǎn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-10-10
  • Java中的反射機(jī)制示例詳解

    Java中的反射機(jī)制示例詳解

    反射就是把Java類(lèi)中的各個(gè)成分映射成一個(gè)個(gè)的Java對(duì)象。本文將通過(guò)示例詳細(xì)講解Java中的反射機(jī)制,感興趣的小伙伴可以跟隨小編學(xué)習(xí)一下
    2022-03-03
  • springboot3+r2dbc響應(yīng)式編程實(shí)踐

    springboot3+r2dbc響應(yīng)式編程實(shí)踐

    本文主要介紹了springboot3+r2dbc響應(yīng)式編程實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Java中小球碰撞并使用按鈕控制數(shù)量實(shí)例代碼

    Java中小球碰撞并使用按鈕控制數(shù)量實(shí)例代碼

    這篇文章主要給大家介紹了關(guān)于Java中小球碰撞并使用按鈕控制數(shù)量的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-12-12
  • SpringBoot actuator 健康檢查不通過(guò)的解決方案

    SpringBoot actuator 健康檢查不通過(guò)的解決方案

    這篇文章主要介紹了SpringBoot actuator 健康檢查不通過(guò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Struts2攔截器登錄驗(yàn)證實(shí)例

    Struts2攔截器登錄驗(yàn)證實(shí)例

    本篇文章主要介紹了Struts2攔截器登錄驗(yàn)證實(shí)例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • MyBatis?超詳細(xì)講解動(dòng)態(tài)SQL的實(shí)現(xiàn)

    MyBatis?超詳細(xì)講解動(dòng)態(tài)SQL的實(shí)現(xiàn)

    動(dòng)態(tài)?SQL?是?MyBatis?的強(qiáng)大特性之一。如果你使用過(guò)?JDBC?或其它類(lèi)似的框架,你應(yīng)該能理解根據(jù)不同條件拼接?SQL?語(yǔ)句有多痛苦,例如拼接時(shí)要確保不能忘記添加必要的空格,還要注意去掉列表最后一個(gè)列名的逗號(hào)。利用動(dòng)態(tài)?SQL,可以徹底擺脫這種痛苦
    2022-03-03
  • 利用Java如何獲取IP與機(jī)器名方法示例

    利用Java如何獲取IP與機(jī)器名方法示例

    在開(kāi)發(fā)工作中,我們常常需要獲取客戶端的IP。下面這篇文章主要給大家介紹了關(guān)于利用Java如何獲取IP與機(jī)器名的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-07-07
  • SpringBoot+Eureka實(shí)現(xiàn)微服務(wù)負(fù)載均衡的示例代碼

    SpringBoot+Eureka實(shí)現(xiàn)微服務(wù)負(fù)載均衡的示例代碼

    這篇文章主要介紹了SpringBoot+Eureka實(shí)現(xiàn)微服務(wù)負(fù)載均衡的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Java?中?hashCode()?與?equals()?的關(guān)系(面試)

    Java?中?hashCode()?與?equals()?的關(guān)系(面試)

    這篇文章主要介紹了Java中hashCode()與equals()的關(guān)系,ava中hashCode()和equals()的關(guān)系是面試中的??键c(diǎn),文章對(duì)hashCode與equals的關(guān)系做出詳解,需要的小伙伴可以參考一下
    2022-09-09

最新評(píng)論