“归并排序”

三、归并排序

归并排序的基本思想:

​ 将一个数组不断地折半划分,当划分的数组足够小的时候每个区段中只有一个元素,每次比较都会都会使子序列有序,最后合并成原始的有序数列。归并排序是稳定的排序算法。

具体的算法实现:

  1. MergeSort函数递归实现对原数组的折半划分
  2. _Merge函数实现对字序列的排序
  3. memcpy函数是c/c++的内存拷贝函数

函数原型

void *memcpy(void *destin, void *source, unsigned n);

参数

  • destin– 指向用于存储复制内容的目标数组,类型强制转换为 void 指针。

  • source– 指向要复制的数据源,类型强制转换为 void* 指针。

  • n– 要被复制的字节数。

功能

从源source所指的内存地址的起始位置开始拷贝n个字节到目标destin所指的内存地址的起始位置中。

归并排序的算法时间复杂度分析:

​ 归并的时间复杂度分析:主要是考虑两个函数的时间花销,一、数组划分函数 MergeSort();二、有序数组归并函数_ Merge();

​ _Merge()函数的时间复杂度为O(n),因为代码中有2个长度为n的循环(非嵌套),所以时间复杂度则为O(n);

简单的分析下元素长度为n的归并排序所消耗的时间 T[n]:调用MergeSort()函数划分两部分,那每一小部分排序好所花时间则为 T[n/2],而最后把这两部分有序的数组合并成一个有序的数组_Merge()函数所花的时间为 O(n);

​ 公式:T[n] = 2T[n/2] + O(n)=O(nlog(n));

#include <stdio.h>
#include <string.h>

//分组归并
void _Merge(int *a, int begin1, int end1, int begin2, int end2, int *tmp)
{
	int index = begin1;
	int i = begin1, j = begin2;
	//注意:当划分的区间足够小时,begin1==end1,begin2==end2
	while (i <= end1&&j <= end2){
		if (a[i]<=a[j])
			tmp[index++] = a[i++];
		else
			tmp[index++] = a[j++];
	}
	//将左边元素填充到tmp中
	while (i <= end1)
		tmp[index++] = a[i++];
	//将右边元素填充的tmp中
	while (j <= end2)
		tmp[index++] = a[j++];
	//将tmp中的数据拷贝到原数组对应的序列区间
	memcpy(a + begin1, tmp + begin1, sizeof(int)*(end2 - begin1 + 1));
}
//归并排序
void MergeSort(int *a, int left, int right, int *tmp)
{
	if (left >= right)
		return;
	//mid将数组二分
	int mid = left + ((right - left) >> 1);
	//左边归并排序,使得左子序列有序
	MergeSort(a, left, mid, tmp);
	//右边归并排序,使得右子序列有序
	MergeSort(a, mid + 1, right, tmp);
	//将两个有序子数组合并
	_Merge(a, left, mid, mid + 1, right, tmp);
}
//打印数组
void PrintArray(int *a, int len)
{
	for (int i = 0; i < len; i++)
		printf("%d ", a[i]);
	printf("\n");
}
int main()
{
	int i,n; 
	scanf("%d",&n);
	int a[n],tmp[n];
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	
	MergeSort(a,0,n-1,tmp);
	PrintArray(a,n);
	
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值