归并排序(c语言)

归并排序

归并定义:将两个或以上的有序表组合成一个新的有序表。
归并排序:假设初始序列含义n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,知道得到一个长度为n的有序序列为止——2路归并排序。

归并排序过程:逐一两两分开,再两两归并
逐一两两分开,最终分成一个个单独的元素,再一一进行比较、合并。

代码分析:
代码主要分为两个部分,分解过程和合并过程
利用递归来实现分解和合并的过程,其中if(s==t) TR1[s]=SR[s];表示分解完毕,开始递归返回进行合并

void MSort(int SR[],int TR1[],int s,int t){		
	int m;
	int TR2[MAX+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);	
	} 
}

复杂度分析:
一趟归并排序需将SR[1]–Sr[n]汇总相邻的长度h有序序列进行两两归并,会访问到数组中的每一个数,故一次递归的复杂度为n,由完全二叉树的性质知,需进行(log2n)次递归,故总的时间复杂度为O(nlog2n)

归并排序倒过来看就是一棵完成二叉树
在这里插入图片描述
归并排序完整代码:(详细注释)

/*
Author:Kim
Data:2020-2-10
Topic:归并排序的递归实现法代码
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 10

//	定义一个用于的排序的顺序表
typedef struct SL {
	int r[MAX+1];//	用于存储要排序的数,通常:r[0]作为哨兵或者临时变量 
	int length;//	用于记录顺序表的长度 
}SqList;

//合并函数
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 
	}
}

//	将SR[]递归排序为TR1[] 
void MSort(int SR[],int TR1[],int s,int t){		
	int m;
	int TR2[MAX+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);	
	} 
}

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

int main() {
	SqList t;
	t.length = 0;
	int a[] = { 20,10,50,90,70,40,80,60,30 };
	int i;
	for (i = 0; i < 9; i++)	t.r[i + 1] = a[i];
	t.length = 9;
	printf("初始序列:");
	for (i = 1; i < 10; i++)	printf("%3d", t.r[i]);
	printf("\n");
	
	//	归并排序
	MergeSort(&t);
	printf("归并排序后序列:");
	for (i = 1; i < 10; i++)	printf("%3d", t.r[i]);
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值