17-归并排序

这一章我们讲解分治算法。

1、分治的基本概念

把一个任务,分成形式和原任务相同,但规模更小的几个部分任务(通常是两个部分),分别完成,或只需要选一部完成。然后再处理完成后的这一个或几部分的结果,实现整个任务的完成。

分治实例 – 称假币
16枚硬币,有可能有1枚假币,假币比真币轻。有一架天 平,用最少称量次数确定有没假币,若有的话,假币是哪一枚。
8 – 8 一称,发现无假币,或假币所在的那8枚
4 – 4 一称
2 – 2 一称
1 – 1 一称

了解的分治的思想后,我们开看一下具体的问题,归并排序的问题。

2、归并排序

数组排序任务可以如下完成:

  1. 把前一半排序
  2. 把后一半排序
  3. 把两半归并到一个新的有序数组,然后再拷贝回原数组,排序完成

将两个排序好的数组归并过程如下:
在这里插入图片描述

#include<iostream>
using namespace std;
typedef int ElementType;
//L = 左边起始位置, R = 右边起始位置, RightEnd = 右边终点位置
void Merge(ElementType A[], ElementType TmpA[],
int L, int R, int RightEnd)
{
	int LeftEnd = R - 1;
	int len = RightEnd - L + 1;
	int i = L;
	while (L<=LeftEnd && R<=RightEnd)
	{
		if (A[L]>A[R])
			TmpA[i++] = A[R++];
		else
			TmpA[i++] = A[L++];
	}
	while (L <= LeftEnd)
		TmpA[i++] = A[L++];
	while (R <= RightEnd)
		TmpA[i++] = A[R++];
	for (int i = 0; i < len; i++,RightEnd--)
		A[RightEnd] = TmpA[RightEnd];
}

void MSort(ElementType A[], ElementType TmpA[], int L, int RightEnd)
{
	if(L<RightEnd)
	{
		int center = (L + RightEnd) / 2;
		MSort(A,TmpA,L,center);
		MSort(A,TmpA,center+1,RightEnd);
		Merge(A,TmpA,L,center+1,RightEnd);
	}
}

void Merge_Sort(ElementType A[], int N)
{
	ElementType *TmpA = (int *)malloc(N*sizeof(ElementType));
	if (TmpA != NULL)
	{
		MSort(A, TmpA, 0, N - 1);
		free(TmpA);
	}
	else
		cout << "空间不足";
}

int main()
{
	int a[] = { 4, 6, 1, 8, 9, 3, 7, 0 };
	int len = sizeof(a) / sizeof(a[0]);
	Merge_Sort(a, len);
	for (int i = 0; i < len; i++)
		cout << a[i] << " ";
	return 0;
}

归并排序的时间复杂度

对n个元素进行排序的时间:
T(n) = 2*T(n/2) + a*n (a是常数,具体多少不重要)
= 2*(2*T(n/4)+a*n/2)+a*n
= 4*T(n/4)+2a*n
= 4*(2*T(n/8)+a*n/4)+2*a*n
= 8*T(n/8)+3*a*n

= 2k *T(n/2k)+k*a*n

一直到n/2k = 1 (此时k = log2n)
T(n)= 2k *T(1)+k*a*n
= 2k+k*a*n
= n+a*(log2n)*n

复杂度为O(nlogn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值