演算法 8 歸併排序

2021-10-02 06:55:24 字數 3297 閱讀 4749

目錄

1、描述

2、特點

3、自頂向下的歸併排序

4、自底向上的歸併排序

5、歸併排序的優化

6、使用場景

7、歸併排序是一種漸進最優的基於比較排序的演算法。

歸併排序是基於遞迴方式進行排序的。它其實可以分為兩步:

第一步 遞迴,(遞迴就是將陣列遞迴拆分成很小的陣列)

第二步,合併。(合併就是將這些很小的陣列比較合併成有序的陣列)

它的核心思想是乙個長度為n的陣列,按2的倍數,不斷遞迴拆分成子陣列,拆分到最後,每個陣列只有兩個元素的時候,將子陣列a中兩個元素比較,交換成有序的子陣列,然後和有序的子陣列(同等級,長度為2)b合併成c,子陣列c這時候有4個元素,然後和他同等級的有序子陣列d(長度=4)再合併,以此類推........最後合併成乙個有序的完整的陣列。

就那這個圖說明,陣列a長度是16,遞迴拆分後,每個陣列中的元素都是兩個(奇數陣列會有剩乙個的情況),然後將a[0..1]比較換成有序,然後和a[2..3]合併,再然後將a[0..3]和a[4..7]合併,最後再將a[0..7]和[8..15]合併,這樣原陣列就排序完成了。

這裡忘說了一點,排序中的比較和交換位置,都是在合併的時候完成的。

自頂向下的意思就是將陣列從大陣列不斷拆分子陣列,然後進行比較合併的。

public class merge 

/*** 遞迴拆分

*/public static void sort(double a, int lo, int hi)

}/**

* 將子陣列合併

*/private static void merge(double a, int lo, int mid, int hi)

int i = lo;

int j = mid + 1;

for (int k = lo; k <= hi; k++)

}private static void exch(double a, int i, int j)

private static void show(double a)

}public static void main(string args) ;

sort(a);

show(a);}}

上面的**的拆分和合併的過程如下圖:

自底向上的思想就是先將2個2個元素比較換成有序,然後再將4個4個的元素比較換成有序,然後是8個、16個、32個。

public class mergebu 

}private static void exch(double a, int i, int j)

private static void show(double a)

}public static void main(string args) ;

sort(a);

show(a);}}

我們的優化從三方面入手:

1、如果遞迴拆分的陣列長度小於7(建議取值5~15)的話,我們採用插入排序來加快排序的速度。下圖綠色框

2、將拷貝陣列aux作為引數穿進去。這樣能節省每次merge時,拷貝陣列的時間(空間消耗沒減小)。下圖紅色框

3、當a[0..1]和a[2..3]合併的時候,如果a[1]比a[2]小,說明這兩個陣列的順序是依次排的,這樣就可以減少一次合併。下圖藍色框

60000條資料的話,優化後要比原始的歸併排序快了0.8倍。

for 60000 random doubles

全部優化 is 0.8 times faster than 從頂向下歸併排序

for 60000 random doubles

快速排序 is 0.7 times faster than 從頂向下歸併排序

for 60000 random doubles

希爾排序 is 1.2 times faster than 從頂向下歸併排序

for 60000 random doubles

插入排序 is 123.4 times faster than 從頂向下歸併排序

對於長度為 n 的任意陣列,自頂向下的歸併排序需要 1⁄2nlgn 至 nlgn 次比較。

對於長度為 n 的任意陣列,自頂向下的歸併排序最多需要訪問陣列 6nlgn 次

適用場景1:上面的1和2點說明了歸併排序能夠保證將任意長度為 n 的陣列排序所需時間和 nlogn 成正比,這樣讓它擁有了可以處理數百萬甚至更大的陣列排序。但是缺點輔助陣列aux導致的額外空間和n的大小成正比。

適用場景2:自底向上的歸併排序比較適合用鍊錶組織的資料。想象一下將鍊錶先按大小為 1 的子鍊錶進行 排序,然後是大小為 2 的子鍊錶,然後是大小為 4 的子鍊錶等。這種方法只需要重新組織鍊錶鏈結 就能將鍊錶原地排序(不需要建立任何新的鍊錶結點)。

下面命題 i 說明沒有任何排序演算法能夠用少於 ~nlgn 次比較將陣列排序,這是其他排序演算法複雜度的下限。歸併排序在最壞情況下的比較次數和任意基於比較的其他排序演算法所需的最少比較次數都是 ~nlgn。

歸併演算法 歸併排序

歸併演算法 歸併排序 這周需要用到歸併演算法,於是找了找相關的資料,整理如下 歸併排序 merge sort 是利用 歸併 技術來進行排序。歸併是指將若干個已排序的子檔案合併成乙個有序的檔案。兩路歸併演算法 1 演算法基本思路 設兩個有序的子檔案 相當於輸入堆 放在同一向量中相鄰的位置上 r low...

歸併排序演算法

include stdafx.h include include include 合併兩段已經排好序的列表 void merge int list int mergelist int left int mid int right else if i mid else 將列表list按照seglen分...

歸併排序演算法

這個演算法感覺比插入難理解一些,下面說說我的理解 歸併排序的步驟 1.把長度為n的序列分為兩個長度為n 2的子串行 2.對這兩個子串行分別採用歸併排序 3.將兩個子串行合併成乙個最終的排序序列 通過步驟2可看到 在歸併排序中又用了歸併排序,可見這是乙個遞迴的過程。例如乙個陣列 a 8 下面採用遞迴排...