这个程序使用分治法计算最大子段,结果为最大子段之和,用递归程序实现。

原始数据使用随机函数生成。

采用结构化程序设计,可以很容易改为从标准输入或文件读入数据,只需要修改函数getData即可。

数据个数由宏定义给出,也可以轻松地改为输入

/*
 * 最大子段算法程序
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 13

void getData(int [], int);

int maxsumfun(int a[], int left, int right);

int main(void)
{
    int a[N], i;

    getData(a, N); /* 获得数据放入数组a中 */

    printf("datas: ");
    for (i = 0; i < N; i++)
        printf("%d ", a[i]);
    printf("\n");

    int ms;
    ms = maxsumfun(a, 0, N - 1);

    printf("maxsum=%d\n", ms);

    return 0;
}

int maxsumfun(int a[], int left, int right)
{
    int maxsum = 0;

    if(left == right)
    {
        if(a[left] > 0)
            maxsum = a[left];
        else
            maxsum = 0;
    }
    else
    {
        int mid, leftsum, rightsum, midsum;

        mid = (left + right) / 2;
        leftsum = maxsumfun(a, left, mid);
        rightsum = maxsumfun(a, mid+1, right);

        int leftsum1 = 0;
        int lefts = 0;
        int i;
        for(i=mid; i>=left; i--)
        {
            lefts += a[i];
            if(lefts > leftsum1)
                leftsum1 = lefts;
        }

        int rightsum1 = 0;
        int rights = 0;
        for(i=mid+1; i<=right; i++)
        {
            rights += a[i];
            if(rights > rightsum1)
                rightsum1 = rights;
        }

        midsum = leftsum1 + rightsum1;
        if(midsum < leftsum)
            maxsum = leftsum;
        else
            maxsum = midsum;
        if(maxsum < rightsum)
            maxsum = rightsum;
    }
    return maxsum;
}

void getData(int d[], int n)
{
    time_t t;
    srand((unsigned) time(&t));  /* 设置随机数起始值 */

    int i;
    for(i=0; i < n; i++)
        d[i] = rand() % 30 - 10; /* 获得-10--20之间的整数值 */
}

关键代码:

// 递归计算最大子段
int maxsumfun(int a[], int left, int right)
{
    int maxsum = 0;

    if(left == right)
    {
        if(a[left] > 0)
            maxsum = a[left];
        else
            maxsum = 0;
    }
    else
    {
        int mid, leftsum, rightsum, midsum;

        mid = (left + right) / 2;
        leftsum = maxsumfun(a, left, mid);
        rightsum = maxsumfun(a, mid+1, right);

        int leftsum1 = 0;
        int lefts = 0;
        int i;
        for(i=mid; i>=left; i--)
        {
            lefts += a[i];
            if(lefts > leftsum1)
                leftsum1 = lefts;
        }

        int rightsum1 = 0;
        int rights = 0;
        for(i=mid+1; i<=right; i++)
        {
            rights += a[i];
            if(rights > rightsum1)
                rightsum1 = rights;
        }

        midsum = leftsum1 + rightsum1;
        if(midsum < leftsum)
            maxsum = leftsum;
        else
            maxsum = midsum;
        if(maxsum < rightsum)
            maxsum = rightsum;
    }
    return maxsum;
}