排序算法的c++實現——歸併排序

    歸併排序是典型分治思想的表明——首先把原問題分解爲兩個或多個子問題,而後求解子問題的解,最後使用子問題的解來構造出原問題的解。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   }
相關文章
相關標籤/搜索