/*************************************************************************
	File Name: maxSubSequence.c
	Author: ***
	Mail: *******@**.com 
	Created Time: 2015年07月18日 19:38:14
	Description:求最大子序列的四种算法,数据结构与算法分析(C语言版)第二章 
 ************************************************************************/
#include
#include
#include



int MaxSubSequenceSum1(int A[],int n,int *start,int *end)
{
    int sum,maxSum,i,j,k;
    maxSum=A[0];
    *start=*end=1;

    /* 找出A[0...n-1]序列中的最大子序列,通过不断的遍历所有可能的起点,去寻找终点 */
    for(i=0;imaxSum)
            {
                maxSum=sum;
                *start=i+1;

                //最内层循环已经结束;k==j+1;
                *end=k;
            }    
        }
    }
    return maxSum;
}


int MaxSubSequenceSum2(const int A[],const int n,int *start,int *end)
{
    /* 这个算法和算法1原理一样,只是算法1在内循环中进行了不必要的计算 */
    int sum,maxSum,i,j;
    maxSum=A[0];
    *start=*end=1;

    /* 找出A[0...n-1]序列中的最大子序列,通过不断的遍历所有可能的起点,去寻找终点 */
    for(i=0;imaxSum)
            {
                maxSum=sum;
                *start=i+1;
                *end=j+1;
            }    
        }
    }
    return maxSum;

}

/* 分治算法 */
int MaxSubSequenceSum3(int A[],int left,int right,int *start,int *end)
{
    int MaxL,MaxR,ls,le,rs,re,MaxM,ms,me,MidLeft,MidLeftMax,
        MidRight,MidRightMax,Mid,i;
    
    //基本情况
    if(left==right)
    {
        *start=*end=left;
        return A[left-1];
    }
    
    //计算中间点
    Mid=(left+right)/2;

    //计算左边部分最大子序列
    MaxL=MaxSubSequenceSum3(A,left,Mid,&ls,&le);

    //计算右边部分最大子序列
    MaxR=MaxSubSequenceSum3(A,Mid+1,right,&rs,&re);


    //计算中间部分最大子序列
    MidLeft=0;
    MidLeftMax=A[Mid-1];
    ms=Mid;
    for(i=Mid;i>=left;i--)
    {
        MidLeft+=A[i-1];
        if(MidLeft>MidLeftMax)
        {
            MidLeftMax=MidLeft;
            ms=i;
        }
    }
    MidRight=0;
    MidRightMax=A[Mid];
    me=Mid+1;
    for(i=Mid+1;i<=right;i++)
    {
        MidRight+=A[i-1];
        if(MidRight>MidRightMax)
        {
            MidRightMax=MidRight;
            me=i;
        }
    }
    MaxM=MidLeftMax+MidRightMax;
    
    //获得最大子序列
    if(MaxL>MaxR&&MaxL>MaxM)
    {
        *start=ls;
        *end=le;
        return MaxL;
    }
    else if(MaxR>MaxL&&MaxR>MaxM)
    {
        *start=rs;
        *end=re;
        return MaxR;
    }
    else
    {
        *start=ms;
        *end=me;
        return MaxM;
    }
}


int MaxSubSequenceSum4(int A[],int n,int *start,int *end)
{
    int sum,maxSum,i;
    sum=0;
    maxSum=A[0];
    *start=*end=1;
    for(i=0;imaxSum)
        {
            maxSum=sum;
            *end=i+1;
        }
        //sum小于0,表示最大子序列不可能包括这部分序列
        else if(sum<0)
        {
            sum=0;
            *start=*end=i+2;
        }
    }
    return maxSum;
}

int main()
{
    int A[16]={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7},start,end;

    printf("%d\n",MaxSubSequenceSum1(A,16,&start,&end));
    printf("%d  %d\n",start,end);
    printf("%d\n",MaxSubSequenceSum2(A,16,&start,&end));
    printf("%d  %d\n",start,end);
    printf("%d\n",MaxSubSequenceSum3(A,1,16,&start,&end));
    printf("%d  %d\n",start,end);
    printf("%d\n",MaxSubSequenceSum4(A,16,&start,&end));
    printf("%d  %d\n",start,end);
    return 0;
}