分治法求最大最小值

分治法解求最大最小值问题

问题描述:在含有n个不同元素的集合a[n]中同时找出它的最大值和最小值。不妨设n=2m次方,m>=0。

分治法
基本思想:将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同。递归的解决这些子问题,然后再将这些子问题合并得到原问题的解。

Divide-and-Conquer(P)
{
	if(|P|<=n0)Adboc(P);
	divide P into smaller subinstances
	P1,P2,...,Pk;
	for(i=1;i<=k;i++)
	yi=Divide-and-Conquer(Pi);
	return Merge(y1,y2,...yk);
}

分治法的基本框架
 其中,|P|是问题P的规模,n0为一阙值,表示当问题P的规模不超过n0时,问题已经容易被解决,不需要继续被分解。Adhoc§是该分治法中的基本子算法,用于直接解决最小的子问题。Merge(y1,y2,…yk)是该分治法中的合并子算法,用于合并P的子问题。
 不难发现,实现分治法的保障是递归,如何构建好递归非常重要,递归的确定需要确定两个部分,分别为递归边界和递归方法。回到本问题,问题需要我们输入问题规模n和问题的具体数字(用整型数组a来存储)。
例:问题规模n=8,具体数字a[]={22,10,60,78,45,51,8,36}。通过对分治法和递归算法的了解我们不难构建出问题函数的过程图。
在这里插入图片描述

递归边界:
SL和SR是左右子问题返回的最大值与最小值的结构体

if(i==j)
	{
		s.max=s.min=b[i];
		return s;
	}
	if(i==j-1)
	{
		if(b[i]>=b[j])
		{
			s.max=b[i];
			s.min=b[j];
			return s;
		}
		if(b[i]<b[j])
		{
			s.max=b[j];
			s.min=b[i];
			return s;
		}
	}

递归函数:

	SL=MAXMIN(i,mid,b);
	SR=MAXMIN(mid+1,j,b);

合并:

	if(SL.max>SR.max)
		s.max=SL.max;
	else
		s.max=SR.max;
	if(SL.min>SR.min)
		s.min=SR.min;
	else
		s.min=SL.min;
	return s;

注意
1(递归边界).我们在设计算法的时候,根据算法中的递归边界可以确定需要确定子问题中的最左边标志i最右边标志j ,在划分子问题的时候我们还得定义一个中间变量mid 作为左子问题的最右边界和mid+1作为右子问题的最左边界。
2(递归函数).试想,我们把一组数据分为左右两个子问题,每个子问题都需要求出一个最大值和最小值返回,函数返回的时候,为了减少算法的复杂程度,我们可以用C语言当中的结构体变量,定义一个结构体变量S,其中包含两个整型变量最大值max和最小值min。
3(合并算法).在合并子问题的时候,左右子问题都会产生各自的最大值和最小值,左子问题的最大值SL.max最小值SL.min,右子问题的最大值SR.max最小值SR.min。两边的最大值比较,最大的就是该问题的最大值max,两边的最小值比较,最小值就为该问题的最小值min。
代码如下

#include<stdio.h>
#include<windows.h>
typedef struct 
{
	int max;
	int min;
}S;
S MAXMIN(int i,int j,int b[]){
	S s,SL,SR;
	int mid;
	if(i==j)
	{
		s.max=s.min=b[i];
		return s;
	}
	if(i==j-1)
	{
		if(b[i]>=b[j])
		{
			s.max=b[i];
			s.min=b[j];
			return s;
		}
		if(b[i]<b[j])
		{
			s.max=b[j];
			s.min=b[i];
			return s;
		}
	}
	mid=(i+j)/2;
	SL=MAXMIN(i,mid,b);
	SR=MAXMIN(mid+1,j,b);
	if(SL.max>SR.max)
		s.max=SL.max;
	else
		s.max=SR.max;
	if(SL.min>SR.min)
		s.min=SR.min;
	else
		s.min=SL.min;
	return s;
}
void main(){
	int k,n,a[100];
	S d;
	printf("输入问题规模n:");
	scanf("%d",&n);
	printf("输入问题的数字:");
	for(k=0;k<=n-1;k++)
	{
		scanf("%d",&a[k]);
	}
	d=MAXMIN(0,n-1,a);
	printf("最大值为:%d,最小值为:%d\n",d.max,d.min);
	system("pause");
}

  • 12
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值