排序算法之歸並排序(Mergesort)解析


一.歸並排序的優缺點(pros and cons)

耗費心思來理解它,總要有個理由吧:

  • 歸並排序的效率達到了巔峰:時間復雜度為O(nlogn),這是基於比較的排序算法所能達到的最高境界
  • 歸並排序是一種穩定的算法(即在排序過程中大小相同的元素能夠保持排序前的順序,3212升序排序結果是1223,排序前后兩個2的順序不變),這一點在某些場景下至關重要
  • 歸並排序是最常用的外部排序方法(當待排序的記錄放在外存上,內存裝不下全部數據時,歸並排序仍然適用,當然歸並排序同樣適用於內部排序...)

缺點:

  • 歸並排序需要O(n)的輔助空間,而與之效率相同的快排和堆排分別需要O(logn)和O(1)的輔助空間,在同類算法中歸並排序的空間復雜度略高

P.S.本文只討論最原始的“兩路歸並”,多路的與之類似

二.內部原理

首先要知道歸並排序的思想是:分治法,與快速排序的思想一樣

算法思想:無序 ->  部分有序  ->  整體有序

歸並排序中“分”與“合”的過程是結合在一起的,即每一趟都在做“分”與“合”的工作,並不是先“分”完再“合”(“分”很簡單,不就是一直二分二分直到不可再分唄,額,這么想就錯了,分完就合不起來了,切記“分”與“合”是結合在一起的)

用一幅圖來解釋歸並排序的過程就足夠了:

說明:P1與P2比較,將較大(小)者裝入P,然后P1或者P2右移(裝了誰就移誰),最后P右移

比如要對數組a[n]做升序排序,那么具體過程如下:

  1. 申請兩個長度都為n/2的輔助空間,把a數組裝進去,前一半裝進L,后一半裝進R
  2. 按照說明中的方式做一輪比較(P從A移動到C,一趟結束)

現在想想我們做完一趟排序得到了什么?

  1. 達成了部分有序(前一半 < 后一半,對吧?)
  2. 除此之外,我們很自然的把待排序序列一分為二,為遞歸做好了准備

還不夠清晰?那么還有幾句話:

  1. 圖示的過程解釋了為什么需要長度為n的輔助空間
  2. 只要L和R各自內部都有序(同升序或者同降序),那么只需要再經過一趟歸並,排序就完成了(仔細想想,沒錯吧?)
  3. 排序部分就是合並部分(還記得上面提過的那句話嗎?“分”與“合”的過程是結合在一起的,千萬不能分開想,否則你會發現合不起來了...)

三.實現細節

如果上面的解釋還不夠清晰,那么我們來舉個例子,一步步分析:

假定待排序序列為a[] = {3, 2, 1, 4},那么具體過程是這樣的:

P.S.如果待排序序列是奇數個怎么辦?這是問題嗎?無非是拆得的前一半比后一半少一個而已,單趟循環控制是由P指針來做的,不存在某個P1沒有與之配對的P2可以比的問題

四.總結

歸並排序多用於需要外部排序的場景,除此之外當內部排序需要保證穩定性時也采用歸並排序(不要求穩定性的內部排序一般采用快排或者堆排序,前者在待排序序列基本有序時效率低,后者堆的維護是個問題)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM