昨天开始看《数据结构与算法分析-java语言描述》这本书,在第二章举例了一个算法问题“最大子序列和问题”,在第三种递归方法,由于开始并没有很好理解,递归调用在算法中有很重要,用了最简单一个例子来加深理解!(当然这种方法在这四种算法中不是最优的)。
先给出源代码:
package secondCHA;
public class maxSUM3 {
static int MaxSubSum( int A[], int Left, int Right) //问题?初始left和right是先给定的吗?值是多少
{
int MaxLeftSum,MaxRightSum;
int MaxLeftBorderSum,MaxRightBorderSum;
int LeftBorderSum,RightBorderSum;
int Center,i;
//递归终点,left>right的情况是不可能出现的,除非N是负数。
if(Left == Right)
{
if(A[Left] > 0)
return A[Left];
else
return 0;
}
Center = (Left + Right)/2;
//重点,递归部分
MaxLeftSum = MaxSubSum(A,Left,Center);
MaxRightSum = MaxSubSum(A,Center+1,Right);
// 计算left达到中间分界处的两个最大和的和数
MaxLeftBorderSum = 0;
LeftBorderSum = 0;
for(i = Center;i >= Left;i--)
{
LeftBorderSum += A[i];
if(LeftBorderSum > MaxLeftBorderSum)
MaxLeftBorderSum = LeftBorderSum;
}
// 计算right达到中间分界处的两个最大和的和数
MaxRightBorderSum = 0;
RightBorderSum = 0;
for(i = Center+1;i <= Right;i++)
{
RightBorderSum += A[i];
if(RightBorderSum > MaxRightBorderSum)
MaxRightBorderSum = RightBorderSum;
}
return Max(MaxLeftSum,MaxRightSum,MaxLeftBorderSum + MaxRightBorderSum);
}
static int Max(int a, int b, int c)
{
if(a>b&&a>c)
return a;
else if(b>a&&b>c)
return b;
else
return c;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a={4,-3,5,-2,-1,2,6,-2};
int left=0;
int right=a.length-1;
System.out.println(MaxSubSum(a,left,right));
}
}
用8个元素的数组进行分析:
A0 |
A1 |
A2 |
A3 |
A4 |
A5 |
A6 |
A7 |
4 |
-3 |
5 |
-2 |
-1 |
2 |
6 |
-2 |
第一次:MaxSubSum(A,0,7)
A0 |
A1 |
A2 |
A3 |
A4 |
A5 |
A6 |
A7 |
4 |
-3 |
5 |
-2 |
-1 |
2 |
6 |
-2 |
Int center=(0+7)/2=3
左边(A0-A3)部分包含最后一个元素的最大值为:
LeftBorderSum=Max(A3,A3+A2,A3+A2+A1,A3+A2+A1+A0)=4
右边(A4-A7)部分包含第一个元素的最大值为:
RightBorderSum=Max(A4,A4+A5,A4+A5+A6,A4+A5+A6+A7)=7
return Max(MaxLeftSum,MaxRightSum,MaxLeftBorderSum + MaxRightBorderSum=11);
MaxSubSum(A,0,7)=return Max(MaxSubSum(A,0,3),MaxSubSum(A,4,7),11);
第一次的返回值采用了中MaxLeftSum = MaxSubSum(A,0,3)和MaxRightSum = MaxSubSum(A,4,7)采用了递归,则需先确定MaxSubSum(A,0,3)和MaxSubSum(A,4,7),因为引出了第二次分析。
第二次:MaxSubSum(A,0,3),MaxSubSum(A,4,7)
1 MaxSubSum(A,0,3)
A0 |
A1 |
A2 |
A3 |
4 |
-3 |
5 |
-2 |
Int center=(0+3)/2=1
左边(A0-A1)部分包含最后一个元素的最大值为:
LeftBorderSum=Max(A1,A1+A0,)=1
右边(A2-A3)部分包含第一个元素的最大值为:
RightBorderSum=Max(A2,,A2+A3)=5
return Max(MaxLeftSum,MaxRightSum,MaxLeftBorderSum + MaxRightBorderSum=6);
MaxSubSum(A,0,3)=return Max(MaxSubSum(A,0,1),MaxSubSum(A,2,3),6);
2 MaxSubSum(A,4,7)
A4 |
A5 |
A6 |
A7 |
-1 |
2 |
6 |
-2 |
Int center=(4+7)/2=5
左边(A4-A5)部分包含最后一个元素的最大值为:
LeftBorderSum=Max(A5,A5+A4)=2
右边(A6-A7)部分包含第一个元素的最大值为:
RightBorderSum=Max(A6,A6+A7)=6
return Max(MaxLeftSum,MaxRightSum,MaxLeftBorderSum + MaxRightBorderSum=8);
MaxSubSum(A,4,7)=return Max(MaxSubSum(A,4,5),MaxSubSum(A,6,7),8);
第三次MaxSubSum(A,0,1),MaxSubSum(A,2,3),MaxSubSum(A,4,5),MaxSubSum(A,6,7)
1.1 MaxSubSum(A,0,1)
A0 |
A1 |
4 |
-3 |
MaxSubSum(A,0,1)=return Max(MaxSubSum(A,0,0),MaxSubSum(A,1,1),1);
1.2 MaxSubSum(A,2,3)
A2 |
A3 |
5 |
-2 |
MaxSubSum(A,2,3)=return Max(MaxSubSum(A,2,2),MaxSubSum(A,3,3),3);
2.1 MaxSubSum(A,4,5)
A4 |
A5 |
-1 |
2 |
MaxSubSum(A,4,5)=return Max(MaxSubSum(A,4,4),MaxSubSum(A,5,5),1);
2.2 MaxSubSum(A,6,7)
A6 |
A7 |
6 |
-2 |
MaxSubSum(A,6,7)=return Max(MaxSubSum(A,6,6),MaxSubSum(A,7,7),4);
第四次MaxSubSum(A,0,0),MaxSubSum(A,1,1),MaxSubSum(A,2,2),MaxSubSum(A,3,3),MaxSubSum(A,4,4),MaxSubSum(A,5,5),MaxSubSum(A,6,6),MaxSubSum(A,7,7)
这时到达递归终点,由left=right
if(Left == Right)
{
if(A[Left] > 0)
return A[Left];
else
return 0;
}
因此:MaxSubSum(A,0,0)=4,MaxSubSum(A,1,1)=0,MaxSubSum(A,2,2)=5,MaxSubSum(A,3,3)=0,MaxSubSum(A,4,4)=0,MaxSubSum(A,5,5)=2,MaxSubSum(A,6,6)=6,MaxSubSum(A,7,7)=0
递归结束,则将递归终点按第四次-第三次-第二次-第一次返回。
MaxSubSum(A,0,0)=4,MaxSubSum(A,1,1)=0,MaxSubSum(A,2,2)=5,MaxSubSum(A,3,3)=0,MaxSubSum(A,4,4)=0,MaxSubSum(A,5,5)=2,MaxSubSum(A,6,6)=6,MaxSubSum(A,7,7)=0.
MaxSubSum(A,0,1)=return Max(MaxSubSum(A,0,0),MaxSubSum(A,1,1),1)=4
MaxSubSum(A,2,3)=return Max(MaxSubSum(A,2,2),MaxSubSum(A,3,3),3)=5
MaxSubSum(A,4,5)=return Max(MaxSubSum(A,4,4),MaxSubSum(A,5,5),1)=2;
MaxSubSum(A,6,7)=return Max(MaxSubSum(A,6,6),MaxSubSum(A,7,7),4)=6
MaxSubSum(A,0,3)=return Max(MaxSubSum(A,0,1),MaxSubSum(A,2,3),6)=6
MaxSubSum(A,4,7)=return Max(MaxSubSum(A,4,5),MaxSubSum(A,6,7),8)=8
MaxSubSum(A,0,7)=return Max(MaxSubSum(A,0,3),MaxSubSum(A,4,7),11)=11
总结:在理解递归的时候可以把他看做一个黑盒子,采用归纳证明发的思想,重点关注递归终点和递归方法。例如本例子中,这个方法的思想是,最大子序列可能有三种情况:左边,右边和包含左右挨着的元素组。就可以求左边最大,右边最大,左右同时包含最大,这三者中的最大值,其中左右同时包含的最大值是可以求得的,因此只需求左最大和右最大,这里又可以把左最大和右最大看成2个独立元素组......递归循环。递归终点,就是进入死循环或者无法继续,这时当left=right时,就需要终点程序。