3.歸并排序

1.什么是歸并排序?

歸并:將兩個(gè)有序數(shù)組合并成一個(gè)更大的有序數(shù)組。

歸并排序有兩個(gè)主要操作:遞歸和合并。
要將一個(gè)數(shù)組排序,可以先(遞歸的)將它分半分別排序,然后將結(jié)果歸并起來(lái),這就是歸并排序。
我們知道遞歸的主要思想是分治思想,而這也是歸并排序的思想。

2.歸并的抽象方法

歸并方法主要講數(shù)組左側(cè)(a[lo..mid])和數(shù)組右側(cè)(a[mid+1..hi])歸并成一個(gè)有序的數(shù)組并將結(jié)果防止到a[lo..hi]中。
在下面的實(shí)現(xiàn)中,我們將借助一個(gè)輔助數(shù)組aux:

public static void merge(int[] a, int lo, int mid,int hi){
  // i代表mid左側(cè)的角標(biāo),j代表mid右側(cè)的角標(biāo),每次向數(shù)組a中放入左側(cè)的元素時(shí)i++,向數(shù)組a中放入右側(cè)的元素時(shí)j++
  int i = lo, j= mid;
  //將原數(shù)組復(fù)制到輔助數(shù)組中
  for(int k = lo;k <= hi; k++){
     aux[k] = a[k];
  }
  
  for(int k = lo; k <= hi; k++){
    //1.左側(cè)用盡取右側(cè)
    if(i > mid)  a[k] = aux[j++];
    //2.右側(cè)取盡取左側(cè)
    else if(j>hi) a[k] = aux[i++];
    //3.左側(cè)元素大于右側(cè)元素時(shí)取右側(cè)
    else if(a[i] > a[j])  a[k] = aux[j++];
    //4.左側(cè)元素小于右側(cè)元素時(shí)取左側(cè)
    else a[k] = aux[i++];    
  }
}

歸并完成后,下面要實(shí)現(xiàn)遞歸,遞歸的順序有兩種方式:

1.自頂向下
2.自底向上

3.自頂向下的歸并排序
public class Merge{
  private static int[] aux;
  public static void sort(int[] a){
   //一次性分配空間
    aux = new int[a.length];
    mergeSort(a,0,a.length - 1);
  }
  //遞歸方法
  private static void mergeSort(int[] a; int lo; int hi){
    //跳出遞歸的條件
    if(lo >= hi) return;
    int mid = lo + (hi - lo)/2;
    mergeSort(a,lo,mid);//將左側(cè)排序
    mergeSort(a,mid,hi);//將右側(cè)排序    
    merge(a,lo,mid,hi);//歸并結(jié)果 
  }
}
4.自底向上的歸并排序

這種實(shí)現(xiàn)方法比標(biāo)準(zhǔn)的遞歸代碼量更少。首先我們進(jìn)行的是兩兩歸并(把每個(gè)元素想象成一個(gè)大小為1的數(shù)組),然后是四四歸并(將兩個(gè)大小為2的數(shù)組歸并成一個(gè)大小為4的數(shù)組),然后是八八歸并...

public class MergeBU {
    public static void sort(int[] a) {
        int n = a.length;
        int[] aux = new Comparable[n];
        for (int len = 1; len < n; len *= 2) {
            for (int lo = 0; lo < n-len; lo += len+len) {
                int mid  = lo+len-1;
                int hi = Math.min(lo+len+len-1, n-1);
                merge(a, aux, lo, mid, hi);
            }
        }
    }
}

自底向上的歸并.png

自底向上的歸并排序比較適合采用鏈表的數(shù)據(jù),這種方法只需要重新組織鏈表鏈接就能將鏈表原地排序(不需要?jiǎng)?chuàng)建新的鏈表結(jié)點(diǎn))。

5.復(fù)雜度

對(duì)于長(zhǎng)度為N的數(shù)組,歸并排序所需的時(shí)間和NlogN成正比;它的主要缺點(diǎn)是:所需要的額外空間和N成正比。

參考資料:https://algs4.cs.princeton.edu/22mergesort/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 歸并排序以?(N logN)最壞情形運(yùn)行時(shí)間運(yùn)行,而所使用的比較次數(shù)幾乎是最優(yōu)的。 這個(gè)算法的基本操作是合并兩個(gè)已...
    MinkChannel閱讀 408評(píng)論 0 0
  • 1 初級(jí)排序算法 排序算法關(guān)注的主要是重新排列數(shù)組元素,其中每個(gè)元素都有一個(gè)主鍵。排序算法是將所有元素主鍵按某種方...
    深度沉迷學(xué)習(xí)閱讀 1,609評(píng)論 0 1
  • 接下來(lái)準(zhǔn)備學(xué)習(xí)一下歸并排序去別的blog看了一段,很多博客概括介紹歸并的時(shí)候是這樣子的: 基本理念:分治思想(di...
    阿飛不理飛閱讀 413評(píng)論 0 0
  • 最近在讀< >時(shí),了解到了很多常用的排序算法,故寫一篇讀書筆記記錄下這些排序算法的思路和實(shí)現(xiàn). 冒泡排序 冒泡排序...
    SylvanasSun閱讀 829評(píng)論 0 0
  • Q:什么是歸并排序?A:它是建立在歸并操作上的一種有效的排序算法;是采用分治法的一個(gè)非常典型的應(yīng)用;是一種穩(wěn)定的 ...
    TinyDolphin閱讀 3,124評(píng)論 5 4

友情鏈接更多精彩內(nèi)容