最大子段问题 分治算法

 

分治算法就是将一个问题分解成若干个小问题,对若干个小问题分别求解,最后在合并起来

最大子段问题课以分成三种情况
1.数组a[1-n](即数组前1至n个元素) 的最大子段和a[1-n/2]的最大子段相同
2数组a[1-n](即数组前1至n个元素) 的最大子段和a[n/2+1-n]的最大子段相同
3.数组a[1-n]的最大子段和是由a[1-n/2]和a[n/2+1-n]结合而成,求解方法为
则分别求出
         n/2                  i
   max    ∑a[k] 和   max     ∑a[k] ,然后将两个值相加即得到此种情况下的数组最大子段和
0<=i<=n/2 k=i      n/2+1<=i<=n k=n/2


最后分别求出三种情况的最大子段和,再比较三个子段和,最大的那个即为数组的最大字段和

 

源代码:

// 最大子段 分治算法.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
/*****************************************************88
定义了一个存储结果的结构体
*******************************************************888*/
struct result
{
	int max;//存储最大字段值
	int startindex;//存储最大字段开始下标
	int endindex;//存储最大字段结束下标
};
/********************************************************
函数名: Phalf
参数类型:int a[] , int n1 , int n2
返回值:struct result
功能:求在数组的n1至n2间的最大字段
***********************************************************/
struct result Phalf(int a[] , int n1 , int n2)
{
	struct result half;
	int flags = 0;
	//int max = 0;
	for(int i=n1;i<n2;i++)
	{
		int sum = a[i];
		if(flags==0)
		  {
            half.max = sum;
			flags = 1;
		  }
		if(sum>half.max)
	{
		half.max = sum;
		half.startindex = i;
		half.endindex = i;
	}
		for(int j=i+1;j<n2;j++)
		{
          sum += a[j];
		  if(sum>half.max)
		  {
			  half.max = sum;
			  half.startindex = i;
			  half.endindex = j;
		  }
		}
		
	}
	return half;
}
/**********************************************
函数名:summax
参数类型:int a[] , int n
返回值:struct result
功能:当数组a的最大子段既不在前半段中也不在后半段中
则分别求出n/2                 i
   max    ∑a[k] 和   max    ∑a[k] ,然后将两个值相加
0<=i<=n/2 k=i      n/2+1<=i<=n k=n/2

***********************************************/
struct result summax(int a[] , int n)
{
	int Fhalfmax;
	int Shalfmax;
	int Fsum;
	int Ssum;
	int flags = 0;
	struct result half;
	half.startindex = 0;
	half.endindex = (n+1)/2;
	for(int i=0;i<(n+1)/2-1;i++)
	{
		Fsum = a[i];
		if(flags==0)
		{
			Fhalfmax = Fsum;
			flags =1 ;
		}
		for(int j=i+1;j<(n+1)/2;j++)
		{
           Fsum += a[j];
		}
		
		if(Fhalfmax<Fsum)
		{
			Fhalfmax = Fsum;
            half.startindex = i;
		}

	}
	if(Fhalfmax<a[(n+1)/2-1])
	{
		Fhalfmax = a[(n+1)/2-1];
		half.startindex = (n+1)/2-1;
	}

		Ssum = a[(n+1)/2];
		if(flags==1)
		{
			Shalfmax = Ssum;
			flags =0 ;
		}
		for(int j1=(n+1)/2+1;j1<n;j1++)
		{

        Ssum += a[j1];
		if(Shalfmax<Ssum)
		{
			Shalfmax = Ssum;
            half.endindex = j1;
		}
		}


	if(Shalfmax<a[n-1])
	{
		Shalfmax = a[n-1];
		half.endindex = n-1;
	}

	half.max = Shalfmax+Fhalfmax;
	return half;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int a[10];
	int flags = 1;
	for(int i=0;i<10;i++)
		scanf("%d" , &a[i]);
	struct result half[3];
	half[0] = Phalf(a , 0 , 5);
	half[1] = Phalf(a , 5 , 10);
	half[2] = summax(a , 10);
	int max = half[0].max;;
	int index = 0;
	for(int i=1;i<3;i++)
	{
		if(half[i].max>max)
		{
			max = half[i].max;
			index = i;
		}
	}
	printf("max = %d , startindex = %d , endindex = %d\n" , half[index].max , half[index].startindex , half[index].endindex);
	return 0;
}

运行结果:

第一种情况:

 

第二种情况:

第三种情况:


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值