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(" "); 63 return 0; 64 }