最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入探究TimSort對(duì)歸并排序算法的優(yōu)化及Java實(shí)現(xiàn)

 更新時(shí)間:2016年05月04日 11:27:49   作者:Lizo_Is_Me  
這篇文章主要介紹了TimSort歸并排序的優(yōu)化及Java實(shí)現(xiàn),TimSort 是一個(gè)歸并排序做了大量?jī)?yōu)化的版本,需要的朋友可以參考下

簡(jiǎn)介
MergeSort對(duì)已經(jīng)反向排好序的輸入時(shí)復(fù)雜度為O(n^2),而timsort就是針對(duì)這種情況,對(duì)MergeSort進(jìn)行優(yōu)化而產(chǎn)生的,平均復(fù)雜度為n*O(log n),最好的情況為O(n),最壞情況n*O(log n)。并且TimSort是一種穩(wěn)定性排序。思想是先對(duì)待排序列進(jìn)行分區(qū),然后再對(duì)分區(qū)進(jìn)行合并,看起來和MergeSort步驟一樣,但是其中有一些針對(duì)反向和大規(guī)模數(shù)據(jù)的優(yōu)化處理。

歸并排序的優(yōu)化思想
歸并排序有以下幾點(diǎn)優(yōu)化方法:

和快速排序一樣,對(duì)于小數(shù)組可以使用插入排序或者選擇排序,避免遞歸調(diào)用。
在merge()調(diào)用之前,可以判斷一下a[mid]是否小于等于a[mid+1]。如果是的話那么就不用歸并了,數(shù)組已經(jīng)是有序的。原因很簡(jiǎn)單,既然兩個(gè)子數(shù)組已經(jīng)有序了,那么a[mid]是第一個(gè)子數(shù)組的最大值,a[mid+1]是第二個(gè)子數(shù)組的最小值。當(dāng)a[mid]<=a[mid+1]時(shí),數(shù)組整體有序。
為了節(jié)省將元素復(fù)制到輔助數(shù)組作用的時(shí)間,可以在遞歸調(diào)用的每個(gè)層次交換原始數(shù)組與輔助數(shù)組的角色。
在merge()方法中的歸并過程需要判斷i和j是否已經(jīng)越界,即某半邊已經(jīng)用盡??梢杂昧硪环N方式,去掉檢測(cè)是否某半邊已經(jīng)用盡的代碼。具體步驟是將數(shù)組a[]的后半部分以降序的方式復(fù)制到aux[],然后從兩端歸并。對(duì)于數(shù)組{1,2,3}和{2,3,5},第一個(gè)子數(shù)組照常復(fù)制,第二個(gè)則從后往前復(fù)制,最終aux[]中的元素為{1,2,3,5,3,2}。這種方法的缺點(diǎn)是使得歸并排序變?yōu)椴环€(wěn)定排序。代碼實(shí)現(xiàn)如下:

void merge(int[] a, int lo, int mid, int hi, int[] aux) {
for (int k = lo; k <= mid; k++) {
  aux[k] = a[k];
}
for (int k = mid + 1;k <= hi; k++) {
  aux[k] = a[hi - k + mid + 1];
}
int i = lo, j = hi;   //從兩端往中間
for (int k = lo; k <= hi; k++)
  if (aux[i] <= aux[j]) a[k] = aux[i++];
  else a[k] = aux[j--];
}

TimSort的步驟

分區(qū)

分區(qū)的思想是掃描一次數(shù)組,把連續(xù)正序列(如果是升序排序,那么正序列就是升序序列),或者【嚴(yán)格】(保證排序算法的穩(wěn)定性)的反序列做為一個(gè)分區(qū)(run),如果是反序列,把分區(qū)里的元素反轉(zhuǎn)一下。 例如
1,2,3,6,4,5,8,6,4 劃分分區(qū)結(jié)果為
[1,2,3,6],[4,5,8],[6,4]
然后反轉(zhuǎn)反序列
[1,2,3,6],[4,5,8],[4,6]

合并

考慮一個(gè)極端的例子,比如分區(qū)的長(zhǎng)度分別為 10000,10,1000,10,10,我們當(dāng)然希望是先讓10個(gè)10合并成20, 20和1000合并成1020如此下去, 如果從從左往右順序合并的話,每次都用到10000這個(gè)數(shù)組和去小的數(shù)組合并,代價(jià)太大了。所以我們可以用一個(gè)策略來優(yōu)化合并的順序。

實(shí)例

以java中的ComparableTimSort.sort()為例子, 用了一個(gè)run stack來確定是否應(yīng)該合并,

    if (nRemaining < MIN_MERGE) {
      int initRunLen = countRunAndMakeAscending(a, lo, hi);
      binarySort(a, lo, hi, lo + initRunLen);
      return;
    }


小于MIN_MERGE(32)的排序,分區(qū)后直接用二分插入排序

int minRun = minRunLength(nRemaining);
    do {
      //找出下一個(gè)分區(qū)的起始位置,同時(shí)也對(duì)反向序列做了翻轉(zhuǎn)處理
      int runLen = countRunAndMakeAscending(a, lo, hi);

      //保證run stack中的run的都大于minRun ,如果當(dāng)前分區(qū)太小,就從后面取出元素補(bǔ)足
      if (runLen < minRun) {
        int force = nRemaining <= minRun ? nRemaining : minRun;
        binarySort(a, lo, lo + force, lo + runLen);
        runLen = force;
      }

      //把run放入 run stack中
      ts.pushRun(lo, runLen);
      //判斷是否應(yīng)該合并,i是從棧頂開始的,知道不能合并為止
      //1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1] 
      //2. runLen[i - 2] > runLen[i - 1]
      ts.mergeCollapse();


      lo += runLen;
      nRemaining -= runLen;
    } while (nRemaining != 0);

    // Merge all remaining runs to complete sort
    assert lo == hi;
    //合并剩下的run
    ts.mergeForceCollapse();
    assert ts.stackSize == 1;


在看里面的一個(gè)比較重要的函數(shù)

/**
* 如果后2個(gè)run的長(zhǎng)度加起來比前面一個(gè)長(zhǎng),則使用中間位置的run和前后長(zhǎng)度更短的run一個(gè)合并
* 如果后2個(gè)run的長(zhǎng)度加起來比前面一個(gè)短,則把后面2個(gè)run合并
*/
 private void mergeCollapse() {
    while (stackSize > 1) {
      int n = stackSize - 2;
      if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1]) {
        if (runLen[n - 1] < runLen[n + 1])
          n--;
        mergeAt(n);
      } else if (runLen[n] <= runLen[n + 1]) {
        mergeAt(n);
      } else {
        break; // Invariant is established
      }
    }
  }

相關(guān)文章

  • springBoot下實(shí)現(xiàn)java自動(dòng)創(chuàng)建數(shù)據(jù)庫表

    springBoot下實(shí)現(xiàn)java自動(dòng)創(chuàng)建數(shù)據(jù)庫表

    這篇文章主要介紹了springBoot下實(shí)現(xiàn)java自動(dòng)創(chuàng)建數(shù)據(jù)庫表的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • JAVA面試題 簡(jiǎn)談你對(duì)synchronized關(guān)鍵字的理解

    JAVA面試題 簡(jiǎn)談你對(duì)synchronized關(guān)鍵字的理解

    這篇文章主要介紹了JAVA面試題 請(qǐng)談?wù)勀銓?duì)Sychronized關(guān)鍵字的理解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • jvm調(diào)優(yōu)常用命令行工具詳解

    jvm調(diào)優(yōu)常用命令行工具詳解

    這篇文章主要介紹了jvm調(diào)優(yōu)常用命令行工具的用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Spring加載屬性文件方式(自動(dòng)加載優(yōu)先級(jí)問題)

    Spring加載屬性文件方式(自動(dòng)加載優(yōu)先級(jí)問題)

    這篇文章主要介紹了Spring加載屬性文件方式(自動(dòng)加載優(yōu)先級(jí)問題),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 高并發(fā)系統(tǒng)的限流詳解及實(shí)現(xiàn)

    高并發(fā)系統(tǒng)的限流詳解及實(shí)現(xiàn)

    這篇文章主要介紹了高并發(fā)系統(tǒng)的限流詳解及實(shí)現(xiàn),內(nèi)容詳細(xì),小編覺得很不錯(cuò),這里分享給大家,供需要的朋友參考。隨小編一起看看吧。
    2017-11-11
  • springboot使用DynamicDataSource動(dòng)態(tài)切換數(shù)據(jù)源的實(shí)現(xiàn)過程

    springboot使用DynamicDataSource動(dòng)態(tài)切換數(shù)據(jù)源的實(shí)現(xiàn)過程

    這篇文章主要給大家介紹了關(guān)于springboot使用DynamicDataSource動(dòng)態(tài)切換數(shù)據(jù)源的實(shí)現(xiàn)過程,Spring Boot應(yīng)用中可以配置多個(gè)數(shù)據(jù)源,并根據(jù)注解靈活指定當(dāng)前使用的數(shù)據(jù)源,需要的朋友可以參考下
    2023-08-08
  • Java圖像處理之RGB調(diào)色面板

    Java圖像處理之RGB調(diào)色面板

    這篇文章主要為大家詳細(xì)介紹了Java圖像處理之RGB調(diào)色面板,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 簡(jiǎn)單了解Spring Cloud搭建Config過程實(shí)例

    簡(jiǎn)單了解Spring Cloud搭建Config過程實(shí)例

    這篇文章主要介紹了簡(jiǎn)單了解Spring Cloud搭建Config過程實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • 一文詳解spring注解配置bean的初始化方法和銷毀方法

    一文詳解spring注解配置bean的初始化方法和銷毀方法

    本篇我們講解下spring項(xiàng)目中如何為bean指定初始化方法和銷毀方法。當(dāng)spring完成bean的屬性賦值之后,就會(huì)執(zhí)行bean的初始化方法,而當(dāng)spring要銷毀bean實(shí)例的時(shí)候,也會(huì)調(diào)用bean的銷毀方法。文中有詳細(xì)的代碼實(shí)例,需要的朋友可以參考下
    2023-05-05
  • 一文帶你了解SpringBoot的停機(jī)方式

    一文帶你了解SpringBoot的停機(jī)方式

    停機(jī)簡(jiǎn)單的說,就是向應(yīng)用進(jìn)程發(fā)出停止指令之后,能保證正在執(zhí)行的業(yè)務(wù)操作不受影響,直到操作運(yùn)行完畢之后再停止服務(wù)。本文就來和大家聊聊Springboot的停機(jī)方式與停機(jī)處理
    2023-02-02

最新評(píng)論

治县。| 鄂尔多斯市| 林西县| 平南县| 承德县| 疏附县| 六盘水市| 景宁| 道孚县| 上杭县| 新竹市| 老河口市| 镇宁| 钟山县| 汉阴县| 北宁市| 鹤壁市| 宁陕县| 乌什县| 洪洞县| 五大连池市| 诏安县| 嘉禾县| 蒲城县| 珲春市| 长寿区| 荃湾区| 通海县| 泸水县| 吴忠市| 三原县| 威信县| 中方县| 根河市| 江津市| 靖宇县| 旅游| 凤冈县| 孝昌县| 金秀| 安化县|