歸併排序是典型分治思想的表明——首先把原問題分解爲兩個或多個子問題,而後求解子問題的解,最後使用子問題的解來構造出原問題的解。ios
對於歸併排序,給定一個待排序的數組,首先把該數組劃分爲兩個子數組,而後對子數組進行排序(遞歸調用歸併排序),最後對兩個有序的子數組進行合併,使合併以後的數組爲有序狀態。git
讓咱們想一想,把一個數組不斷地劃分爲子數組,不斷地劃分......,不斷地劃分......., 最後中止了劃分不下去了。 此時子數組的元素有一個,它們自己就是有序的。接下來,咱們就須要執行合併過程,不斷地一層層向上合併,........, 直到原數組。經過這個過程就會發現, 歸併排序的核心在於合併有序的子數組,而不是對子數組進行排序,由於最底層的子數組自己就是有序的,上一層子數組若是想要變成有序的,經過合併底層有序的子數組就能夠獲得, 最終咱們使原數組變成了有序的,從而完成了排序操做。github
說明幾點:redis
1. 歸併排序採用了分治思想,它的核心在於合併子問題的解而不是求解子問題(快速排序也採用了分治思想,但它的核心是在於求解子問題而不須要合併子問題的解)、數組
2. 歸併排序不是原址排序,它有排序過程當中須要藉助額外的內存空間。less
3. 歸併排序爲穩定排序(其實呢,具體還得看你怎麼寫代碼,若是兩個數的值相等時,你不保持原順序都就會變成非穩定的了)函數
4. 歸併排序的時間複雜度爲O(NlogN).測試
具體代碼以下:spa
1 /*********************************************************************** 2 * Copyright (C) 2019 Yinheyi. <chinayinheyi@163.com> 3 * 4 * This program is free software; you can redistribute it and/or modify it under the terms 5 * of the GNU General Public License as published by the Free Software Foundation; either 6 * version 2 of the License, or (at your option) any later version. 7 8 * Brief: 9 * Author: yinheyi 10 * Email: chinayinheyi@163.com 11 * Version: 1.0 12 * Created Time: 2019年05月06日 星期一 22時22分57秒 13 * Modifed Time: 2019年05月09日 星期四 21時10分59秒 14 * Blog: http://www.cnblogs.com/yinheyi 15 * Github: https://github.com/yinheyi 16 * 17 ***********************************************************************/ 18 19 20 // 歸併排序,分治法的典型表明: 將原問題分解了幾個子問題,解決子問題,再合併子問題的解, 21 // 這樣就獲得了原問題的解。 22 // 分治本質上就是把原問題分解爲幾個子問題來解決。 23 // 快速排序也是分治思想來解決。 24 // 25 // 26 // 歸併排序(merge-sort): 27 // 1. 把一個待排序的數組分解爲兩個子數組; 28 // 2. 對兩個子數組進行排序(經過遞歸地調用本身來實現); 29 // 3. 對兩個已經排序的數組進行合併。 30 // 31 // 分析: 32 // 1. 一個數組一直分解下去,只到分解成只包含一個元素的子數組爲止, 此時天然是有序的; 33 // 2. 歸併排序的重點在於合併,而不是對子數組的排序。(快速排序與它偏偏相反,快速排序的 34 // 重點是對子數組進行排序,而不是合併,由於它不須要合併了) 35 // 36 // 37 #include <cstring> 38 #include <iostream> 39 typedef bool(*CompareFunc)(int, int); 40 41 // 下面函數實現合併功能,輸入三個下標參數表示了兩個子數組, :[nStart_, nMiddle)和[nMiddle, nEnd) 42 void Merge(int array[], int nStart_, int nMiddle_, int nEnd_, CompareFunc comp) 43 { 44 if (array == nullptr || nStart_ >= nMiddle_ || nMiddle_ >= nEnd_) 45 return; 46 47 // 創建一個臨時數組存放中間數據 48 int _nIndex = 0; 49 int* _pTempArray = new int[nEnd_ - nStart_]; 50 51 // 對兩個子數組進行合併 52 int _nStartChange = nStart_; 53 int _nMiddleChange = nMiddle_; 54 while (_nStartChange < nMiddle_ && _nMiddleChange < nEnd_) 55 { 56 // 此處的if中比較語句的安排能夠保持穩定排序的特性。 57 if (comp(array[_nMiddleChange], array[_nStartChange])) 58 { 59 _pTempArray[_nIndex] = array[_nMiddleChange]; 60 ++_nMiddleChange; 61 } 62 else 63 { 64 _pTempArray[_nIndex] = array[_nStartChange]; 65 ++_nStartChange; 66 } 67 ++_nIndex; 68 } 69 70 // 把不爲空的子數組的元素追加到臨時數 71 if (_nStartChange < nMiddle_) 72 { 73 memcpy(_pTempArray + _nIndex, array + _nStartChange, sizeof(int) * (nMiddle_ - _nStartChange)); 74 } 75 else if (_nMiddleChange < nEnd_) 76 { 77 memcpy(_pTempArray + _nIndex, array + _nMiddleChange, sizeof(int) * (nEnd_ - _nMiddleChange)); 78 } 79 else 80 { 81 /* do noting */ 82 } 83 84 // 數據交換 85 memcpy(array + nStart_, _pTempArray, sizeof(int) * (nEnd_ - nStart_)); 86 87 delete [] _pTempArray; 88 _pTempArray = nullptr; 89 } 90 91 // 歸併排序功能實現函數 92 void MergeSort(int array[], int nStart_, int nEnd_, CompareFunc comp) 93 { 94 // 數組指針爲空,或者數組內的個數少於等於1個時,直接返回。 95 if (nullptr == array || (nEnd_ - nStart_) <= 1) 96 return; 97 98 // 劃分爲兩個子數組並遞歸調用自身進行排序 99 int _nMiddle = (nStart_ + nEnd_) / 2; 100 MergeSort(array, nStart_, _nMiddle, comp); 101 MergeSort(array, _nMiddle, nEnd_, comp); 102 103 // 合併排序完成的子數組 104 Merge(array, nStart_, _nMiddle, nEnd_, comp); 105 } 106 107 // 比較函數 108 bool less(int lhs, int rhs) 109 { 110 return lhs < rhs; 111 } 112 113 // 打印數組函數 114 void PrintArray(int array[], int nLength_) 115 { 116 if (nullptr == array || nLength_ <= 0) 117 return; 118 119 for (int i = 0; i < nLength_; ++i) 120 { 121 std::cout << array[i] << " "; 122 } 123 124 std::cout << std::endl; 125 } 126 127 /*************** main.c *********************/ 128 >>int main(int argc, char* argv[]) 129 { 130 // 測試1 131 int array[10] = {1, -1, 1, 231321, -12321, -1, -1, 123, -213, -13}; 132 PrintArray(array, 10); 133 MergeSort(array, 0, 10, less); 134 PrintArray(array, 10); 135 136 // 測試2 137 int array2[1] = {1}; 138 PrintArray(array2, 1); 139 MergeSort(array2, 0, 1, less); 140 PrintArray(array2, 1); 141 142 // 測試3 143 int array3[2] = {1, -1}; 144 PrintArray(array3, 2); 145 MergeSort(array3, 0, 2, less); 146 PrintArray(array3, 2); 147 148 return 0; 149 }