/****************************************************************
用分治法解决最大子数组和问题:
最大子数组的位置有以下三种情况:
1:最大子数组位于左半部分A[low,mid]中;
2:最大子数组位于右半部分A[mid+1,high]中;
3:最大子数组跨越了中点,同时位于左半部分和右半部份;
对于第三种情况,最大子数组的和等于从中点开始向左半部分的
最大和加上从中点开始向右半部份的最大和
输入:
第一行为数组元素个数,第二行为数组中的元素值,如下:
16
13 -3 -25 20 -3 -16 -23 18 20 -7 12 -5 -22 15 -4 7
输出:
43
****************************************************************/
#include <stdio.h>
#include <stdlib.h>
//子方法,求跨越中点的最大子数组和,这也相当于分治法中的合并过程
int FIND_MAX_CROSSING_SUBARRAY(int *A,int low,int mid,int high)
{
//从中点向左找出左半部分的最大子数组和
int left_max=-65536;
int sum=0;
for(int i=mid;i>=low;i--)
{
sum=A[i]+sum;
if(sum>left_max)
left_max=sum;
}
//从中点向右找出右半部分的最大子数组和
int right_max=-65536;
sum=0;
for(int i=mid+1;i<=high;i++)
{
sum=A[i]+sum;
if(sum>right_max)
right_max=sum;
}
return left_max+right_max;
}
//主方法,求最大子数组和
int FIND_MAXIMUM_SUBARRAY(int *A,int low,int high)
{
//递归的基本情况
if(low==high)
return A[low];
//递归情况
else
{
int mid=(low+high)/2;
int left_max=FIND_MAXIMUM_SUBARRAY(A,low,mid);
int right_max=FIND_MAXIMUM_SUBARRAY(A,mid+1,high);
int mid_max=FIND_MAX_CROSSING_SUBARRAY(A,low,mid,high);
if(left_max>=right_max&&left_max>=mid_max)
return left_max;
else if(right_max>=left_max&&right_max>=mid_max)
return right_max;
else if(mid_max>=right_max&&mid_max>=left_max)
return mid_max;
}
}
int main()
{
int length;
int *A;
int max,sum,maxi,maxj;
while(scanf("%d",&length)==1)
{
if(length!=0)
{
//输入数组元素
A=(int *)malloc(sizeof(int)*length);
for(int i=0;i<length;i++)
{
scanf("%d",&A[i]);
}
printf("max_sub_sum:%d\n",FIND_MAXIMUM_SUBARRAY(A,0,length-1));
}
else break;
}
return 0;
}
分治策略之最大子数组问题
最新推荐文章于 2021-01-12 21:29:20 发布