七种排序--------归并排序(Merging Sort)

归并排序就是利用归并的思想实现的排序方法。他的原理是假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2] (整数)个长度为2或1的有序子序列;再两两归并,......,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。

先来看代码:

void MergeSort(Sqlist *L)
{
	MSort(L->r,L->r,1,L->length);
}

只是调用了一个函数,封装了一下,假设现在要对数组{50,10,90,30,70,40,80,60,20}进行排序,L.length = 9,则来看看MSort()函数的实现:

void MSort(int SR[],int TR1[],int s,int t)
{
	int m;
	int TR2[MAXSIZE + 1];
	if(s == t)
		TR1[s] = SR[s];
	else
	{
		m = (s + t)/2;
		MSort(SR,TR2,s,m);
		MSort(SR,TR2,m+1,t);
		Merge(TR2,TR1,s,m,t);
	}
}

1.MSort()bei'被调用时,SR与TR1都是{50,10,90,30,70,40,80,60,20},s = 1,t = 9。

2.第5行 显然s不等于t,执行第8~13行语句块。

3.第9行,m = (1+9)/2 = 5,m就是序列的正中间的下标。

4.此时第10行,调用MSort(SR,TR2,1,5)的目标就是将数组SR中的第1~5的关键字归并到有序的TR2(调用前TR2为空数组),第11行调用MSort(SR,TR2,6,9)的目标就是将数组SR中的第6~9的关键字归并到有序的TR2.也就是说,在调用这两句代码之前,代码已经准备将数组分成了两组了。

5.第12行就是分别将数组变得有序。

6.最后递归进去之后总的来说就是按照下图进行递归返回(图来自大话数据结构):

            

再来看一下Merge函数的代码:

扫描二维码关注公众号,回复: 2856206 查看本文章
/*将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n]*/
void Merge(int SR[],int TR[],int i,int m,int n)
{
	int j,k,l;
	for(j = m +1,k = i;i <= m && j <= n;k++)    //将SR中记录由小到大归并到TR
	{
		if(SR[i] < SR[j])
			TR[k] = SR[i++];
		else
			TR[k] = SR[j++];
	}
	
	if(i <= m)
	{
		for(l = 0;l <= m - i;l++)
			TR[k + l] = SR[i + l];              //将剩余的SR[i..m]复制到TR
	}
	
	if(j <= n)
	{
		for(l = 0;l <= n - j;l++)
			TR[k + l] = SR[j + l];              //将剩余的SR[j..n]复制到TR
	}
}

复杂度分析:

时间复杂度为O(nlogn);

空间复杂度为O(n + logn);

非递归实现归并排序

直接看代码:

/*对顺序表L作归并非递归排序*/
void MergeSort2(Sqlist *L)
{
	int *TR = (int *)malloc(L->length*sizeof(int));  //申请额外空间
	int k = 1;
	while(k < L->length)
	{
		MergePass(L->r,TR,k,L->length);
		k = 2*k;                                    //子序列长度加倍
		MergePass(TR,L->r,k,L->length);
		k = 2*k;                                    //子序列长度加倍
	}
}

MergePass()函数的实现:

/*将SR[]中相邻长度为s的子序列两两归并到TR[]中*/
void MergePass(int SR[],int TR[],int s,int n)
{
	int i = 1;
	int j;
	while(i <= n - 2*s + 1)
	{
		Merge(SR,TR,i,i+s-1,i+2*s-1);                  //两两归并
		i = i + 2*s;
	}
	
	if(i < n-s+1)                                      //归并最后两个序列
		Merge(SR,TR,i,i+s-1,n);
	else                                               //若最后只剩下单个子序列
		for(j = i;j <= n;j++)
			TR[j] = SR[j];
}

猜你喜欢

转载自blog.csdn.net/yue_jijun/article/details/81280950
今日推荐