这篇文章是在自学算法导论练习的
直接入正题:
最大连续子序列(分治法)
原理:
一串数组可以对半分,一串数组的最大连续子序列可能是在左端,右端以及跨越中间
依次递归分解求得最小块的最大值,再向上组合成整段最大连续子序列
#include<iostream>
#include<stdlib.h>
using namespace std;
int max(int a,int b,int c)//寻找三者最大
{
int max;
if(a>b)
max=a;
else
max=b;
if(c>max)
max=c;
return max;
}
int MaxCross(int *data,int left,int right)//寻找过中间元素的最大
{
int maxleft,maxright,sum;
int mid=(left+right)/2,k;
if(right-left==1)//如果相距只有1时直接比较(因为mid可能等于左右)
{
return max(data[left],data[right],data[left]+data[right]);
}
maxleft=-100000;//寻找mid左边最大
sum=0;
for(k=mid;k>=left;k--)//注意必须是从mid--
{
sum+=data[k];
if(sum>maxleft)
maxleft=sum;
}
maxright=-100000;//寻找mid右边最大
sum=0;
for(k=mid+1;k<=right;k++)
{
sum+=data[k];
if(sum>maxright)
maxright=sum;
}
return maxleft+maxright;//返回最大和
}
int Findmax(int *data,int left,int right)
{
int maxleft,maxright,maxcross,mid,maxlist;
mid=(left+right)/2;
//左中右顺序可以任意
maxcross=MaxCross(data,left,right);//寻找过中最大
//寻找左边最大
if(mid>left) //如果只有一个元素直接返回
maxleft=Findmax(data,left,mid);
else
maxleft=data[left];
//寻找右边最大
if(mid+1<right)//如果只有一个元素直接返回
maxright=Findmax(data,mid+1,right);
else
maxright=data[right];
return max(maxcross,maxleft,maxright);//返回左中右最大
}
int main()
{
int n,k,*data;
while(1)
{
cout<<"请输入元素个数:";
cin>>n;
data=new int [n];
cout<<"请输入序列:";
for(k=0;k<n;k++)
cin>>data[k];
cout<<Findmax(data,0,n-1)<<endl;
system("pause");
system("cls");
}
}