1. 問題
l 二分歸並排序:對n個不同的數構成的數組A[1..n]進行排序,其中n=2^k
2. 解析
二分歸並排序采用了分治的思想,將序列不斷划分成左右兩個序列,然后依次將小序列進行排序,然后歸並到大序列中。
3. 設計
void Mergesort(int l,int r)
{
int mid = (l + r) >> 1;
if(r - l + 1 <= 1) // 如果序列長度<=1的話那么這個序列必然是有序的
{
return;
}
else if(r - l + 1 == 2) // 如果這個序列的長度 == 2 那么我們可以手動對這個序列進行排序
{
if(arr[r] < arr[l])
{
int t;
t = arr[r];
arr[r] = arr[l];
arr[l] = t;
}
}
else
{
Mergesort(l , mid);
Mergesort(mid + 1, r);
// 當序列長度 > 2時,我們把序列分成兩塊,分別對序列的左子序列,和右子序列進行排序
// 左右子序列排好序之后,我們需要把左右兩個子序列歸並成為一個有序序列
int s1 = l , s2 = mid + 1;
int s = l;
while(s1 <= mid && s2 <= r) // 每次只取兩個子序列中最小,這樣來將兩個子序列歸並到一起
{
if(arr[s1] < arr[s2]) tmp[s++] = arr[s1++];
else tmp[s++] = arr[s2++];
}
while(s1 <= mid) tmp[s++] = arr[s1++];
while(s2 <= r) tmp[s++] = arr[s2++];
for(int i = l ; i <= r; ++ i) arr[i] = tmp[i]; // 把排序好的tmp數組賦值給arr
}
}
4. 分析
時間復雜度:O(nlogn)
解析:每次都將數列分成左右兩個序列,每次歸並的時候需要將元素復制到tmp數組中。又因為最多歸並logn層,每層所需的時間是n。
空間復雜度:O(n)
解析:在歸並的時候需要將元素賦值到tmp數組,因此需要另外開一個tmp數組,這個數組的大小 >= 存有數據的數組的大小。
4. 完整代碼

1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<math.h> 5 #include<algorithm> 6 #include<time.h> 7 8 const int maxn = 1e5 + 100; // 9 10 int arr[maxn] ,tmp[maxn]; // arr數組用於存儲排序前和排序后的序列,tmp數組用於在二分歸並排序的過程中使用 11 int n; // n 代表序列的長度 12 void Mergesort(int l,int r) 13 { 14 int mid = (l + r) >> 1; 15 if(r - l + 1 <= 1) // 如果序列長度<=1的話那么這個序列必然是有序的 16 { 17 return; 18 } 19 else if(r - l + 1 == 2) // 如果這個序列的長度 == 2 那么我們可以手動對這個序列進行排序 20 { 21 if(arr[r] < arr[l]) 22 { 23 int t; 24 t = arr[r]; 25 arr[r] = arr[l]; 26 arr[l] = t; 27 } 28 } 29 else 30 { 31 Mergesort(l , mid); 32 Mergesort(mid + 1, r); 33 // 當序列長度 > 2時,我們把序列分成兩塊,分別對序列的左子序列,和右子序列進行排序 34 // 左右子序列排好序之后,我們需要把左右兩個子序列歸並成為一個有序序列 35 int s1 = l , s2 = mid + 1; 36 int s = l; 37 while(s1 <= mid && s2 <= r) // 每次只取兩個子序列中最小,這樣來將兩個子序列歸並到一起 38 { 39 if(arr[s1] < arr[s2]) tmp[s++] = arr[s1++]; 40 else tmp[s++] = arr[s2++]; 41 } 42 while(s1 <= mid) tmp[s++] = arr[s1++]; 43 while(s2 <= r) tmp[s++] = arr[s2++]; 44 for(int i = l ; i <= r; ++ i) arr[i] = tmp[i]; // 把排序好的tmp數組賦值給arr 45 } 46 } 47 48 49 int main() 50 { 51 srand(time(NULL)); 52 scanf("%d",&n); 53 for(int i = 1 ; i <= n ; ++ i) 54 { 55 arr[i] = rand()%100 + 1; // 通過隨機數生成數組元素 56 } 57 Mergesort(1 , n); 58 for(int i = 1 ; i <= n ; ++ i) 59 { 60 printf("%d ",arr[i]); 61 } 62 printf("\n"); 63 return 0; 64 }