【算法】_012_最大子数组_分治法

1、009_maxsubarr_divcon.h

/***************************************************************
*版权所有 (C)2014,长沙铁信交通科技有限公司。
*
*文件名称:009_maxsubarr_divcon.h
*内容摘要:分治法求取最大子数组
*其它说明:
*当前版本:V1.0
*作   者:伍定湘
*完成日期:2014年9月26日
*
*修改记录1:
*   修改日期:2014年9月26日
*   版本号:V1.0
*   修改人:伍定湘
*   修改内容:创建
***************************************************************/


#ifndef _MAXSUBARR_DIVCON_H_ //防止头文件被重复引用
#define _MAXSUBARR_DIVCON_H_


/**************************************************************
头文件引用
**************************************************************/
#include "typedef.h"//引入内置类型重定义


/**************************************************************
相关宏定义
**************************************************************/


/**************************************************************
相关结构体定义
**************************************************************/
#ifndef _MAXSUBARR_TYPEDEF_ //防止头文件被重复引用
#define _MAXSUBARR_TYPEDEF_
typedef struct
{
    INT32 iOffsetMaxBegin;
    INT32 iOffsetMaxEnd;
    INT32 iSumMax;
}MaxSubArrTypedef;
#endif


/**************************************************************
本程序中出现的函数的声明
**************************************************************/
void maxsubarr_divcon(INT32 aTarget[], const INT32 iArrLen);
MaxSubArrTypedef maxsubarr_divcon_find(const INT32 aTarget[], MaxSubArrTypedef msaTarget);
MaxSubArrTypedef maxsubarr_acrossing(const INT32 aTarget[], const INT32 iOffsetBegin, const INT32 iOffsetMid, const INT32 iOffsetEnd);

#endif


2、009_maxsubarr_divcon.c

/***************************************************************
*版权所有 (C)2014,长沙铁信交通科技有限公司。
*
*文件名称:009_maxsubarr_divcon.c
*内容摘要:分治法求取最大子数组
*其它说明:
*当前版本:V1.0
*作   者:伍定湘
*完成日期:2014年9月27日
*
*修改记录1:
*   修改日期:2014年9月27日
*   版本号:V1.0
*   修改人:伍定湘
*   修改内容:创建
***************************************************************/


/**************************************************************
头文件引用
**************************************************************/
#include "typedef.h"//引入内置类型重定义
#include "009_maxsubarr_divcon.h"

#include <stdio.h>


/**************************************************************
全局变量定义
**************************************************************/


/**************************************************************
函数实现
**************************************************************/

/**********************************************************************
*功能描述:分治法求取最大子数组
*输入参数:aTarget - 目标数组
*        iArrLen - 目标数组的长度
*输出参数:
*返回值:
*其它说明:
*修改日期           版本号         修改人        修改内容
* ---------------------------------------------------------------------
*2014年9月27日      V1.0          伍定湘        创建
***********************************************************************/
void maxsubarr_divcon(INT32 aTarget[], const INT32 iArrLen)
{
	MaxSubArrTypedef msaTarget = { 0, iArrLen - 1, 0 };
	msaTarget = maxsubarr_divcon_find(aTarget, msaTarget);

	printf("iSumMax = %d\n", msaTarget.iSumMax);
	printf("iOffsetMaxBegin = %d\n", msaTarget.iOffsetMaxBegin);
	printf("iOffsetMaxEnd = %d\n", msaTarget.iOffsetMaxEnd);
}

/**********************************************************************
*功能描述:分治法求取最大子数组
*输入参数:aTarget - 目标数组
*        msaTarget - 上一级最大子数组参数
*输出参数:
*返回值:
*其它说明:
*修改日期           版本号         修改人        修改内容
* ---------------------------------------------------------------------
*2014年9月27日      V1.0          伍定湘        创建
***********************************************************************/
MaxSubArrTypedef maxsubarr_divcon_find(const INT32 aTarget[], MaxSubArrTypedef msaTarget)
{
	/* 单元素数组直接返回, 并同时结束了迭代 */
	if (msaTarget.iOffsetMaxBegin == msaTarget.iOffsetMaxEnd)
	{
		msaTarget.iSumMax = aTarget[msaTarget.iOffsetMaxBegin];
		return(msaTarget);
	}

	/* 取中点 */
	INT32 mid = (msaTarget.iOffsetMaxBegin + msaTarget.iOffsetMaxEnd) / 2;

	/* 迭代获取左侧最大子数组 */
	MaxSubArrTypedef msaLeft = {0, 0, 0};//max初始值为0的前提条件是数组值至少有一个正数
	if (mid > msaTarget.iOffsetMaxBegin)//if语句负责过滤引起'起点大于终点'的情况, 并同时结束了迭代
	{
		msaLeft.iOffsetMaxBegin = msaTarget.iOffsetMaxBegin;
		msaLeft.iOffsetMaxEnd = mid - 1;
		msaLeft.iSumMax = 0;
		msaLeft = maxsubarr_divcon_find(aTarget, msaLeft);
	}

	/* 迭代获取右侧最大子数组 */
	MaxSubArrTypedef msaRight = { 0, 0, 0 };
	if (mid < msaTarget.iOffsetMaxEnd)//if语句负责过滤引起'起点大于终点'的情况, 并同时结束了迭代
	{		
		msaRight.iOffsetMaxBegin = mid + 1;
		msaRight.iOffsetMaxEnd = msaTarget.iOffsetMaxEnd;
		msaRight.iSumMax = 0;
		msaRight = maxsubarr_divcon_find(aTarget, msaRight);
	}

	/* 迭代获取跨中点最大子数组 */
	MaxSubArrTypedef msaAcrossMid = maxsubarr_acrossing(aTarget, msaTarget.iOffsetMaxBegin, mid, msaTarget.iOffsetMaxEnd);

	/* 获取三者中和最大的 */
	msaTarget = msaAcrossMid;
	msaTarget = msaTarget.iSumMax > msaLeft.iSumMax ? msaTarget : msaLeft;
	msaTarget = msaTarget.iSumMax > msaRight.iSumMax ? msaTarget : msaRight;

	/* 返回三者中和最大的 */
	return(msaTarget);
}
/**********************************************************************
*功能描述:分治法求取跨过中点的最大子数组
*输入参数:aTarget - 目标数组
*        iOffsetBegin - 目标数组的起点下标
*        iOffsetMid - 目标数组跨过的中点下标
*        iOffsetEnd - 目标数组的终点下标
*输出参数:
*返回值:
*其它说明:
*修改日期           版本号         修改人        修改内容
* ---------------------------------------------------------------------
*2014年9月27日      V1.0          伍定湘        创建
***********************************************************************/
MaxSubArrTypedef maxsubarr_acrossing(const INT32 aTarget[], const INT32 iOffsetBegin, const INT32 iOffsetMid, const INT32 iOffsetEnd)
{
    /* 中点左侧参数 */
    INT32 iOffsetLeft = iOffsetMid;
    INT32 iOffsetMaxLeft = iOffsetMid;
    INT32 iSumMaxLeft = aTarget[iOffsetMid];

    /* 中点右侧参数 */
    INT32 iOffsetRight = iOffsetMid;
    INT32 iOffsetMaxRight = iOffsetMid;
    INT32 iSumMaxRight = aTarget[iOffsetMid];

    /* 求和参数 */
    INT32 iSum;
    INT32 iOffset;

    /* 输出结果 */
    MaxSubArrTypedef msaAcrossMid = { iOffsetMid, iOffsetMid, aTarget[iOffsetMid] };
	
	/* 反向扫描包含iOffsetMid元素左侧的最大子数组 */
    for (; iOffsetLeft >= iOffsetBegin; iOffsetLeft--)
    {
        iSum = 0;
        for (iOffset = iOffsetLeft; iOffset <= iOffsetMid; iOffset++)//求取数组从下标iOffsetLeft到iOffsetMid的元素总和,注意:请勿遗漏等号
        {
            iSum += aTarget[iOffset];
        }
        if (iSum > iSumMaxLeft)//如果新的和大,更新左侧最大的子数组元素之和iSumMaxLeft以及此时子数组起始下标iOffsetMaxLeft
        {
            iSumMaxLeft = iSum;
            iOffsetMaxLeft = iOffsetLeft;
        }
    }

	/* 正向扫描包含iOffsetMid元素右侧的最大子数组 */
    for (; iOffsetRight <= iOffsetEnd; iOffsetRight++)
    {
        iSum = 0;
        for (iOffset = iOffsetMid; iOffset <= iOffsetRight; iOffset++)//求取数组从下标iOffsetMid到iOffsetRight的元素总和,注意:请勿遗漏等号
        {
            iSum += aTarget[iOffset];
        }
        if (iSum > iSumMaxRight)//如果新的和大,更新右侧最大的子数组元素之和iSumMaxRight以及此时子数组起始下标iOffsetMaxRight
        {
            iSumMaxRight = iSum;
            iOffsetMaxRight = iOffsetRight;
        }
    }

    /* 输出结果 */
    msaAcrossMid.iSumMax = iSumMaxLeft + iSumMaxRight - aTarget[iOffsetMid];
    msaAcrossMid.iOffsetMaxBegin = iOffsetMaxLeft;
    msaAcrossMid.iOffsetMaxEnd = iOffsetMaxRight;
    return(msaAcrossMid);
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值