分治法分析及应用

前言

本文主讲分治法的分析以及应用,有三段程序,基于二分查找方法的插入排序,合并排序以及改变合并排序来计算序列中逆序对的个数。


插入排序


大家都不陌生插入排序,其原版如下(最坏情况Θ(n2) ):

void Insertion_Sort(int a[], int p, int r)
{
	int i,j,t;
	for (i = p+1; i < r; i++)
	{
		j = i - 1;
		t = a[i];
		while (a[j] > t && j >= p)
		{
			a[j+1] = a[j];
			j--;
		}
		a[j+1] = t;
	}
}// end of Insertion

基于二分查找方法的插入排序(最坏情况Θ(nlogn) )

/*
	将值A[r+1]插入A[p....r]的非降序序列中  利用的是二分查找方法来插入
*/

void Insertion(int A[], int p, int r)
{
	int i;
	int value = A[r+1];
	int loc = BinaryLocation(A, p, r, value);   //自loc(包括loc)之后的元素全部向后移一位
	for (i = r; i >= loc; i--)
	{
		A[i+1] = A[i];
	}
	A[loc] = value;
}

/*
	插入排序  两种实现方式
*/

void InsertionSort(int A[], int p, int r)
{

   /*********迭代实现*********/
	//int i;

	//for (i = p; i < r; i++)
	//{
	//	Insertion(A, p, i);
	//}

	/*******递归实现*********/
	if (r >= p)
	{
		InsertionSort(A, p, r-1);
		Insertion(A, p, r-1);
	}
}

合并排序


分治思想:

/*
	将R[p....q]和S[q+1....r]合并为A[p.....r]
*/

void Merge(int a[], int p, int q, int r)
{
	int R[100], S[100];
	int i,j,k;

	for ( i = 0; i < q-p+1; i++)        // 将a[p.....q]复制到R[0.....q-p]
	{
		R[i] = a[p+i];                          
	}

	for ( j = 0; j < r-q; j++)               //将a[q+1......r]复制到S[0....r-q-1]
	{
		S[j] = a[j+q+1];
	}

	R[i] = BIG;
	S[j] = BIG;

	i = 0;
	j = 0;

	for ( k = p; k < r+1; k++)             //R,S中的元素全部是非降序排列,将R,S中的较小元素一次复制到数组a中
	{
		if ( R[i] <= S[j])                         
		{
			a[k] = R[i];
			i++;
		}
		else
		{
			a[k] = S[j];
			j++;
			//count += q-p-i+1;             //计算原数组中的逆序对的个数
		}
	}
}

/*
	合并算法
*/

void MergeSort( int a[], int p, int r)
{
	if ( r > p)
	{
		int q = (p + r) / 2;
		MergeSort( a, p, q);
		MergeSort( a, q+1, r);
		Merge( a, p, q, r);
	}
}


求逆序对的个数



逆序:当m<n时A[m]>A[n]则表示(m,n)为一个逆序对。

有两个非降序序列R = {5,6,7,8} , S = {3,6}。则序列T = {5,6,7,8,3,4}的逆序对等于 4+2 = 6个。

当s = 3时,3<5=R[0],所以(r,3)的逆序对个数为length(R)个。

当s = 6时,6<7=R[2],所以(r,3)的逆序对个数为length(R) – 2 =2。

当s < R[i]时,(r,s)的逆序对个数为(length(R) - i)个。

只需修改合并排序算法即可。如代码片段3中的37行,q-p[+1是length(R)的长度。count是全局变量,存储逆序对的个数


总结


分治法的运行时间分析,从代码片段3中的第46行克制

T(n) = 2T(n/2) + cn ,其中cn 是合并函数Merge的运行时间。

T(1) = c

T(n) = 2T(n/2) + cn = 4T(n/4) + 2cn = 8T(n/8) + 3cn = ……. = 2kT(n/2k) + kcn

当k = logn时, T(n) = nT(1) + cnlogn = nc+cnlogn = Θ(nlogn)。

所以看到运行时间包含logn的字眼,应该想到可能需要用到分治法来解决问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值