一、什麼是自底向上的歸併排序?算法
說到底,無論是前面說的自頂向下的歸併排序仍是如今講的自底向上的歸併排序,其實質都是歸併。編程
來看看一個演示過程:數組
這個就是待排序的數組序列性能
先將數組序列以2個元素爲一組分紅4組,每一個組內部分紅2個子序列進行向上合併測試
這是合併以後的效果優化
而後以4個元素爲一組分紅2組,每一個組內部分紅2個子序列進行向上合併spa
這是合併以後的效果code
而後以8個元素爲一組分紅1個組,每一個組內部分紅2個子序列進行向上合併blog
最終整個序列編程有序的了排序
其實從這裏看就能夠知道,這個就好像是前面說的自頂向下排序過程當中的後面一個過程。
二、時間複雜度
同自頂向下的歸併排序相同,時間複雜度也是O(nlogn)級別。
三、算法的實現(基於C++)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
1 /***************************** 自底向上的歸併排序算法實現 ***********************************/ 2 template<typename T> 3 void mergeSortBU (T arr[], int count) 4 { 5 for (int size = 1; size <= count; size += size) { // 外層循環把整個序列分紅多個子序列,size表示一個子序列的元素個數,每一次循環以翻倍的形式增長 6 for (int i = 0; i + size < count; i += size + size) { // 內層循環遍歷全部子序列,以兩個子序列爲一組向上歸併 7 __merge<T>(arr, i, i + size - 1, MIN(i + size + size - 1, count - 1)); // 對兩部分數據進行歸併操做 8 } 9 } 10 } 11 /*******************************************************************************************/
四、性能測試(與通過優化過的自頂向下歸併排序算法相比較)
測試數據量50000:
測試數據量100000:
五、算法優化
其實跟自頂向下歸併排序的優化算法是同樣的
1 /***************************** 自底向上的歸併排序算法實現 ***********************************/ 2 template<typename T> 3 void mergeSortBU (T arr[], int count) 4 { 5 for (int size = 1; size <= count; size += size) { // 外層循環把整個序列分紅多個子序列,size表示一個子序列的元素個數,每一次循環以翻倍的形式增長 6 for (int i = 0; i + size < count; i += size + size) { // 內層循環遍歷全部子序列,以兩個子序列爲一組向上歸併 7 if (MIN(i + size + size - 1, count - 1) - i < 40) { // 優化措施2 8 __insertSortMG<T>(arr, i, MIN(i + size + size - 1, count - 1)); 9 continue; 10 } 11 12 if (arr[i + size - 1] > arr[i + size]) { // 優化措施1 13 __merge<T>(arr, i, i + size - 1, MIN(i + size + size - 1, count - 1)); // 對兩部分數據進行歸併操做 14 } 15 } 16 } 17 } 18 /*******************************************************************************************/
優化事後的性能測試:
測試數據量50000:
測試數據量100000:
總結: 從上面的數據能夠看出來,通過優化以後,自底向上歸併排序的性能獲得了一個很大的提高,
可是仍是比自頂向下歸併排序慢,這個實際上是有緣由的,在這裏不作分析。
還有一個值得一提的就是未通過優化的算法的代碼可知,代碼中沒有使用數組的特性(使用索引找
到對應的元素),因此咱們能夠用自底向上歸併排序對一個鏈表進行排序。