C Algorithm.Max_length

Mark Allen Weiss的data structures and algorithm analysis in c

求一个整数序列的最大的连续子列和:

 1 #include <stdio.h>
 2 
 3 static int Max3( int A, int B, int C )
 4 {
 5     return A > B ? ( A > C ? A : C ) : ( B > C ? B : C );
 6 }
 7 
 8 static int maxsubsum(const int a[], int left, int right)
 9 {
10         int maxleftsum, maxrightsum;
11         int maxleftbordersum, maxrightbordersum;
12         int leftbordersum, rightbordersum;
13         int center, i;
14         
15         if(left == right)
16                 if(a[left] > 0)
17                         return a[left];
18                 else
19                         return 0;
20 
21         center = ( left + right ) / 2;
22         maxleftsum = maxsubsum(a, left, center);
23         maxrightsum = maxsubsum(a, center + 1, right);
24 
25         maxleftbordersum = 0; leftbordersum = 0;
26 
27         for( i = center; i >= left; i--)
28         {
29                 leftbordersum += a[i];
30                 if(leftbordersum > maxleftbordersum)
31                         maxleftbordersum = leftbordersum;
32         }
33 
34         maxrightbordersum = 0; rightbordersum = 0;
35         for(i= center + 1; i<= right; i++)
36         {
37                 rightbordersum += a[i];
38                 if( rightbordersum > maxrightbordersum)
39                         maxrightbordersum = rightbordersum;
40         }
41 
42         return Max3(maxleftsum, maxrightsum, maxleftbordersum + maxrightbordersum);
43 }
44 
45 maxsubsesquencesum( const int a[], int n)
46 {
47         return maxsubsum( a, 0, n-1);
48 }
49 
50 int main()
51 {
52      static int A[ ] = { 4, -3, 5, -2, -1, 2, 6, -2 };
53      static int B[ ] = { -3, -2 };
54         printf( "Maxsum = %d\n", maxsubsesquencesum( B, sizeof( B ) / sizeof( B[ 0 ] ) ) );
55     return 0;
56 }

上面的代码的解释:

把一个序列从中间分成两个子序列,然后对这两个子序列分别求最大子列的和 S1和S2,还有,求出包含中间分界元素的最大子列的和S3, 三者中的最大者就是要求的这整个序列的最大子列的和,Max3(S1, S2,S3)。

这个方法用到了递归方法,即,当所求序列的元素很多时,把他分解成两个更小的子列,当子列分解到只剩下1个元素时,就可以向上返回最大子列的和。

Weiss对基础情况的处理中,有点粗糙了,即上述代码第15~19行中,

15         if(left == right)
16                 if(a[left] > 0)
17                         return a[left];
18                 else
19                         return 0;
为什么当 a[left] <= 0 的时候就要返回0呢,如果整个序列都是负数呢? 那就应该返回此序列中的最大负数就可以了,因为 负数+负数 会越加越小。

Weiss又给出了一个更简洁的算法:
 1 int maxsubsum(int a[], int n)
 2 {
 3     int thisSum=maxSum=0,j;
 4 
 5     for(j=0; j < n; j++)
 6     {
 7         if(thisSum > maxSum)
 8             maxSum=thisSum;
 9         else if(thisSum < 0)
10             thisSum = 0;
11     }
12 
13     return maxSum;
14 }

这个算法的思路是,顺次扫描序列的元素并求其和,如果当前和大于先前保存的最大和,则置最大和为当前和。

如果当前和小于0,则置当前和为0。

这个算法同样假设最大和为负数时,返回0。

 

根据 http://blog.csdn.net/v_JULY_v/article/details/6444021 第一节第3个算法,加上我的一个改进,可以给出序列元素全是负数的情况下的解:

 1 static int maxsubsum(int a[], int n)
 2 {
 3     int thisSum, maxSum, maxelem, j;
 4     thisSum=0;
 5     maxSum=maxelem=a[0];
 6     for(j=0; j < n; j++)
 7     {
 8         if(thisSum>=0)     //如果加上某个元素,sum>=0的话,就加  
 9             thisSum+=a[j];  
10         else     
11             thisSum=a[j];  //如果加上某个元素,sum<0了,就不加  
12         
13         if( maxelem < a[j])
14             maxelem = a[j];
15             
16         if(thisSum > maxSum)
17             maxSum=thisSum;
18             
19         if(maxelem > maxSum)
20             maxSum=maxelem;
21     }
22 
23     return maxSum;
24 }
25 
26 int main()
27 {
28     static int a[] = { 4, -3, 5, -2, -1, 2, 6, -2 };
29     static int b[] = { -4, -3, -5, -2, -1, -2, -6, -2 };
30     static int c[] = { 4, -3, 5, -2, 0, -1, 2, 16, -2 };
31     
32     printf( "Maxsum of a = %d\n", maxsubsum( a, sizeof( a ) / sizeof( a[ 0 ] ) ) );
33     printf( "Maxsum of b = %d\n", maxsubsum( b, sizeof( b ) / sizeof( b[ 0 ] ) ) );
34     printf( "Maxsum of c = %d\n", maxsubsum( c, sizeof( c ) / sizeof( c[ 0 ] ) ) );
35     return 0;
36 }

 

posted @ 2013-12-08 12:22  大馋猫  阅读(284)  评论(0编辑  收藏  举报