算法分析与实践-作业4

二分归并排序

1. 问题

归并排序是建立在归并操作上的一种有效的排序算法,该算法是分治法的一个应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

2. 解析

二分归并排序的工作原理如下:

第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置

第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

重复步骤3直到某一指针超出序列尾

将另一序列剩下的所有元素直接复制到合并序列尾

第四步:将排好序的数组的元素复制到原数组中。

 

例如:设有数列{4,3,2,1}

第一次归并后{3,4},{1,2}

第二次归并后{1,2,3,4}

二分归并排序完成。

3. 设计

 1 #include<stdio.h>
 2 const int maxn=1000+10;
 3 int n;
 4 int a[maxn];
 5 int tmp[maxn];
 6 /*----------以下为二分归并排序算法----------*/ 
 7 void Merge_Sort(int a[],int l,int r){
 8     if(l>=r)return;
 9     int mid=(l+r)/2;
10     Merge_Sort(a,l,mid);
11     Merge_Sort(a,mid+1,r);
12     int now=l-1;
13     int i=l,j=mid+1;
14     while(i<=mid&&j<=r){           //两部分合并 
15         if(a[i]<a[j]){
16             tmp[++now]=a[i];
17             ++i;
18         }
19         else{
20             tmp[++now]=a[j];
21             ++j;
22         }
23     }
24     while(i<=mid){
25         tmp[++now]=a[i];
26         ++i;
27     }
28     while(j<=r){
29         tmp[++now]=a[j];
30         ++j;
31     }
32     for(int i=l;i<=r;++i){
33         a[i]=tmp[i];
34     }
35 }
36 /*----------以上为二分归并排序算法----------*/ 
37 int main(){
38     scanf("%d",&n);
39     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
40     Merge_Sort(a,1,n);
41     for(int i=1;i<=n;++i){
42         printf("%d%c",a[i],i==n?'
':' ');
43     }
44 }

4. 分析

算法复杂度:O(nlogn)

分析:递归分解数据,需要递归logN次,每次都需要对n个数据扫描一次,最好最坏平均都一样,所以O(nlogn)。

1.首先可知

f(n)=2f(n/2)+n

f(n)表示对n个数进行归并排序

2f(n/2)表示将n个数分成两部分分别进行归并排序

n表示对两个子过程结束之后合并的过程。

2.推导

f(n/2)=2*f(n/4)+n/2 当n=n/2时

f(n/4)=2*f(n/8)+n/4 当n=n/4时

……

f(n/2^(m-1))=2*f(n/(2^m))+n/2^(m-1) 当n=n/2^(m-1)时

3.由此可得

f(n)=2^m*f(n/(2^m))+m*n

当m足够大时(仅剩一个数字时),可使得 n/(2^m)=1,此时m=log2(n)

将m代入原式得f(n)=2^(log2(n))*f(1)+n*log2(n),即f(n)=nlog(n)

5. 源码

https://github.com/JayShao-Xie/algorithm-work/blob/master/Merge_Sort.cpp

原文地址:https://www.cnblogs.com/JayShao/p/12520956.html