您的位置:首页 > 编程语言 > C语言/C++

分治算法求最大子数组以及其对应的下标<c/c++源代码>

2014-11-19 21:24 246 查看
参考:http://wenku.baidu.com/link?url=9f_-NmepWw2DoZaj01FHw3udtlS7Pa6fSI-mie-yU1BE8ZLjxgduVPj7B2u-Rfwfbn9eiHuPcp1ggiIccAcN9aLyWmLd3uOux7HbIMc92NG

求解连续子数组的最大值,基本和参考文献一样,本文只是记录了连续子数组的上下界,原文记录上下界方式有误!

更改主要在如下三点:

1、最大值出现在单点上或者连续的几点上,所以在递归算法的收敛位置记录下标值且更新最大值为当前最大值

2、单点出现在分治算法的叶子节点即FIND_MAXIMUM_SUBARRAY的收敛点,连续点出现在分治算法树的父节点即FIND_MAX_CROSSING_SUBARRAY的最值点

3、对于1、2都必须同时更新最大值和最大连续子数组的上下界

#include <iostream>

using namespace std;

#define INF -1000 //定义一个很小的值代表于负无穷

int FIND_MAX_CROSSING_SUBARRAY(int *q,int low,int mid,int high);

int FIND_MAXIMUM_SUBARRAY(int *p,int low,int high);

int pos_low,pos_high,val; //定义全局变量存放起始位置以及满足FIND_MAX_CROSSING_SUBARRAY的和最大值

int max_sum = INF;//

//分治法排序

int main()

{

    int A[]={-1,-2,45,-3,1};

    int *a = A;

    cout<<*(a)<<endl;

    int LEN_A=sizeof(A)/sizeof(int);

    cout<<"maxArrayValues is : "<<FIND_MAXIMUM_SUBARRAY(A,1,LEN_A)<<endl;

    cout<<pos_low<<" "<<pos_high<<" "<<val<<" "<<max_sum<<endl;

    cout<<A[pos_low]<<" "<<A[pos_high]<<endl;

    return 0;

}

//跨中点最大子数组的处理方式,分治方法的核心思想。

//分别计算左右两边的最大子数组,在合并中必被包含在里面。

int FIND_MAX_CROSSING_SUBARRAY(int *q,int low,int mid,int high)

{

    int L_sum, R_sum, sum;

    int max_L, max_R;

    //左边

    L_sum = INF; sum = 0;

    for (int i = mid-1;i >= low-1; i--)

    {

        sum+=*(q+i);

        if (sum > L_sum)//关键部分

        {

            L_sum=sum;//存值,记录位置

            max_L=i;

        }

    }

    //右边

    R_sum=INF;sum=0;

    for (int j=mid;j<high;j++)

    {

        sum+=*(q+j);

        if(sum>R_sum)

        {

            R_sum=sum;

            max_R=j;

        }

    }

    val=L_sum+R_sum;//存储结果

    if(val>max_sum)

    {

        cout<<"1>>>>>>>"<<endl;

        pos_low=max_L,pos_high=max_R;

        max_sum = val;

    }

    return (max_L,max_R,L_sum+R_sum);//返回值表达式为逗号表示式,只返回最后一个量,这一点不完美,所以用全局变量存储

}

//递归程序

int FIND_MAXIMUM_SUBARRAY(int *p,int low,int high)

{

    int mid;

    int data[3];//存放左中右三种情况下的最大子数组的和值

    if (high == low)

    {

        //每次递归都从单个值开始递归计算,可能在单个点上出现最大值

        if(*(p+low-1)>max_sum)

        {

           //保存叶子节点的最大值

           max_sum = *(p+low-1);

           pos_low = low-1;

           pos_high = low-1;

        }

        return (low,high,*(p+low-1));

    }

    else

    {

        mid=(low+high)/2;

        data[0]=FIND_MAXIMUM_SUBARRAY(p,low,mid);//从形参中可以看出范围,分别代表左中右

        data[1]=FIND_MAXIMUM_SUBARRAY(p,mid+1,high);

        data[2]=FIND_MAX_CROSSING_SUBARRAY(p,low,mid,high);

        if ((data[0]>=data[1])&&(data[0]>=data[2]))

        {

            return (data[0]);

        }

        else if ((data[1]>=data[0])&&(data[1]>=data[2]))

        {

            return (data[1]);

        }

        else

        {

            return (data[2]);

        }

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐