二分归并排序算法
1. 問題
對于n個不同的數構成的數組A[1…n]進行排序,其中n = 2k。
2. 解析
二分歸并排序算法原理(假設數組A中共有n個元素):
將數組A中n個元素看成n個獨立的子序列,因此每個子序列的長度為1,然后兩兩合并,得到[n/2]個長度為2或1(注意如果n為奇數時,就會出現多出一個元素無法與其他元素合并)的有序子序列;再兩兩合并,一種重復下去,直到得到一個長度為n的有序數組為止。
二分歸并排序算法實現步驟(分而治之):
1、將待排序數組從中間一分為二,對左右兩邊在進行遞歸分割操作,得到若干個相互獨立的子數組;
2、再對(1)中獲得的若干個獨立的子序列遞歸的執行合并操作,最終得到有序的數組;
3、合并操作的實現(以升序為例):
①假設已經有兩個有序數列,分別存放在兩個數組s,r中;并設i,j分別為指向數組的第一個單元的下標;s有a個元素,r有b個元素;
②再另設一個數組temp,k指向該數組的第一個單元下標;
③比較數組s第i個元素和數組r第j個元素,將小的元素放入數組temp,元素的原先下標與k均往后移動一位;
④重復步驟③,直至i=a或j=b為止。
二分歸并排序算法實現過程(假設n=8):
1、初始化數組A
2、將數組A從中間一分為二
3、對步驟2中所得的兩個數組分別從中間一分為二
4、對步驟3中所得的四個數組分別從中間一分為二
5、按照升序,兩兩合并步驟4中獲得的八個數組
6、按照升序,兩兩合并步驟5中獲得的四個數組
7、按照升序,合并步驟6中獲得的兩個數組
注,:以步驟7為例,分析如何將兩個有序的子序列合并成一個有序序列:
3. 設計
二分歸并排序算法的偽代碼:
void Merge_Sort(int A[], int left, int right){int mid, k, i, j;int temp[Max]; //暫時存儲的數組mid = (left + right) / 2; //標記數組一分為二時的界線k = left; //標記數組temp的下標i = left; //標記前半部分數組的下標 j = mid + 1; //標記后半部分數組的下標if(left == right) return; //當完成數組的拆分時,返回Merge_Sort(left, mid); //對前半部分數組進行歸并排序Merge_Sort(mid + 1, right); //對后半部分數組進行歸并排序while(兩部分數組都未遍歷完){if(前半部分數組中下標為i的元素 > 后半部分數組中下標為j的元素)將下標為j的元素存入數組temp中;k與j均往后移動一位;else將下標為i的元素存入數組temp中;k與i均往后移動一位;}while(若前半部分數組中的全部元素已存在于數組temp中,后半部分數組還未完全遍歷完){將后半部分數組還未遍歷的元素依次存入數組temp中;}while(若后半部分數組中的全部元素已存在于數組temp中,前半部分數組還未完全遍歷完){將前半部分數組還未遍歷的元素依次存入數組temp中;}for(i 到 n){將數組temp中的值依次復制給數組A;} }4. 分析
將一個規模為n的問題分成兩個規模均為n/2的子問題,時間為2T(n/2),又因為合并的時間復雜度為O(n),總時間為T(n) = 2T(n / 2) + O(n)。故,二分歸并排序算法的時間復雜度為O(nlog2n),且最壞、最佳、平均情況下二分歸并排序時間復雜度均為O(nlog2n)。
因為借助了規模為n的temp數組進行排序,故,二分歸并排序算法的空間復雜度為O(n)。
5. 源碼
二分歸并排序算法的源碼地址:
https://github.com/Ying917/Algorithm-Analysis/blob/master/Merge_Sort.cpp
總結
- 上一篇: 需求工程week1
- 下一篇: go run 和 go build 和