分治法之归并排序

上一篇博文介绍了分治法的思想,这一篇我们来了解一下分治法在排序问题中的应用--二路归并排序MergeSort

所谓归并排序是指将两个或两个以上有序的数列(或有序表),合并成一个仍然有序的数列(或有序表)

算法设计思路:

输入:待排序数组a[n],待排序区间[s,t];
输出:升序序列a[s]~a[t]
1 如果s==t,则待排区间只有一个元素,算法结束
2 计算划分中点 m=(s+t)>>1;
3 对前半个子序列a[s]~a[m]进行升序排列
4 对后半个子序列a[m+1]~a[t]进行升序排列
5 合并两个升序序列a[s]~a[m]和a[m+1]~a[t]

算法实现代码(C++)

#include <stdio.h>
const int MAX=20;
//合并两个有序数组中的元素到数组b
void Merge(int a[],int b[],int s,int m,int t)//算法时间复杂度O(n)
{
	int i=s,j=m+1,k=s;
	while(i<=m && j<=t)//取较小者放入b[k]
	{
		if(a[i]<=a[j])
			b[k++]=a[i++];
		else
			b[k++]=a[j++];
	}
	while(i<=m)
		b[k++]=a[i++];
	while(j<=t)
		b[k++]=a[j++];
}
void MergeSort(int a[],int s,int t)
{
	int m,b[MAX];
	if(s==t)
		return ;//平凡问题,递归边界条件,只有一个记录,已经有序
	else
	{
		m=(s+t)>>1;
		MergeSort(a,s,m);
		MergeSort(a,m+1,t);
		Merge(a,b,s,m,t);
		for(int i=s;i<=t;i++)
			a[i]=b[i];
	}
}
extern void test1()
{
		 int length,i;
		 int num[MAX];
		 printf("请输入待排序的数组长度(按ctrl+z结束)\n");
		 while(scanf("%d",&length)!=EOF)
		 {
			 printf("请依次输入数组元素\n");
			 for(i=0;i<length;i++)
				 scanf("%d",num+i);

			 MergeSort(num,0,length-1);
			 printf("\n-------------------------------------------\n");
			 printf("归并排序后输出元素序列\n");
			 for(int i=0;i<length;i++)
				 printf("%d\t",num[i]);
			 printf("\n");
			 for(i=0;i<length;i++)//清零
				 num[i]=0;
			 printf("请输入待排序的数组长度(按ctrl+z结束)\n");
		 }
}

  算法实现分析:

空间复杂度:归并排序需要多元序列上的两个子序列操作,因此不能直接在原序列上进行,需要一个与原序列相同的辅助空间,因此空间复杂度为O(n)

时间复杂度:设待排序列个数为n,则执行一趟合并操作算法时间复杂度为o(n),当n=1时,直接返回,即不耗时间T(1)=0;

总的时间复杂度为t(n)=O(nlogn) 

 

posted @ 2018-04-20 16:37  聊寂园  阅读(541)  评论(0编辑  收藏  举报