首先标明递归的四要素:
关于(1)基准情形,是说必须有不用递归就能求解的情况。否则,递归将永远进行下去。
可以看下这个例子:
int badRecursion( int n )
{
if ( n == 0 )
return 0;
else
return badRecursion ( n/3 + 1 ) + n - 1;
}
你可以算一下,当计算到badRecursion(1)时,将一直计算下去。因为他没有一个终止循环的条件。
(2)(3)很好理解,就不说了。
(4)是说递归算法的效率性。
可以看一下这个递归算法:
long fib(int n)
{
if ( n <= 1 )
return 1;
else
return fib( n - 1 ) + fib( n - 2 );
}
这个算法看起来是个递归,可是当把n的数值调大后会发现它的效率低的惊人。简单分析一下就可以看出,最后一行语句第一次调用 fib(n-1) 实际上同时计算了fib(n-2)。这个信息被抛弃而在最后一行语句第二次调用时又重新计算了一遍。这违反了准则(4)。这可以解释为什么不用递归计算斐波那契数了。
下面是代码和注解
1 int maxSumRec(const vector<int>&a,int left,int right) 2 3 { 4 5 int maxLeftSum,maxRightSum; //表示 6 7 int rightBorderSum = 0,leftBorderSum = 0; 8 9 int maxLeftBorderSum = 0,maxRightBorderSum = 0; 10 11 int center; 12 13 if(left == right) //解决小容量情况,当序列只有一个元素时,非负则返回唯一值,否则返回0(基准情况) 14 15 { 16 17 if(a[left]>0) 18 19 { 20 21 return a[left]; 22 23 }else 24 25 { 26 27 return 0; 28 29 } 30 31 } 32 33 center = (left+right)/2; 34 35 maxLeftSum = maxSumRec(s,left,center); //每次递归返回时,该值为该子段的最终左最大子序列和 36 37 maxRightSum = maxSumRec(s,center+1,right); //每次递归返回时,该值为该子段的右最大自序列和 38 39 for(int i=center;i>=left;i--) //从中间向左扩展求子段的最大子序列和,必然包括子段的最右端数 40 41 { 42 43 leftBorderSum+=s[i]; 44 45 if(leftBorderSum>maxLeftBorderSum) 46 47 { 48 49 maxLeftBorderSum = leftBorderSum; //包含左端数的最大子序列和 50 51 } 52 53 } 54 55 for(int j=center+1;j<=right;j++) //从中间向右扩展求子段的最大子序列和,必然包括子段的最左端数 56 57 { 58 59 rightBorderSum += a[j]; 60 61 if(rightBorderSum > maxRightBorderSum) 62 63 { 64 65 maxRightBorderSum = rightBorderSum; //包含右端数的最大子序列和 66 67 } 68 69 } 70 71 //返回左子最大序列和,右最大子序列,及横跨中间的最大子序列和三者的最大值 72 73 return max3(maxLeftSum,maxRightSum,maxLeftBorderSum+maxRightBorderSum); 74 75 }