递归
什么是递归,简单点,就是当一个函数用它自己来定义时就称为递归。
举个 最简单的例子:
int f(int x){ if(x==0) return 0; else return 2*f(x-1)+x*x;//递归调用 }
当编写递归,关键是要牢记递归的四条基本法则
1. 基准情形。必须总有某些基准情形,它无需递归就能解出。
2. 不断推进。对于那些需要递归求解的情形,每一次递归调用都必须要使得解状况朝近基准情形的方向推进。
3. 设计法则。假设所有的递归调用都能运行。
4. 合成效益法则。在求解一个问题的同一实例时,切勿在不同的递归调用中做重复性的工作。
前面三条原则是保证一个递归调用正确运行,而第四条则是保证递归能够高效运行。
再来个简单的例子:
斐波那契数列,,
int fibo(int n){ if(n==0 || n==1)return 1; else return fibo(n-1)+fibo(n-2); }
此时编写的递归函数就不符合递归的第四条法则,会产生严重的资源消耗。
虽然递归程序存在很大的资源开销,但是递归程序可以简化算法设计,而且有助于给出更加简洁的代码,所以仍然不失为一种好的思想方法。
下面通过几个例子来说明递归在算法设计中的益处。
一。最大子序列和问题。输入-2, 11, -4, 13,-5, –2.答案为20(从第2个到第4个的子序列)下面几种程序设计方法。
1.一个简单的解决方案;
int MaxSubsequenceSum(const int array[], int n){ int thisSum, maxSum, i, j, k; maxSum=0; for(i=0;i<n;++i){ for(j=i;j<n;++j){ thisSum=0; for(k=i;k<=j;++k){ thisSum+=array[k]; } if(thisSum>maxSum){ maxSum=thisSum; } } } return maxSum; }
此时我们分析知道该算法的时间复杂度为:O().
2.对前一种算法的小改进。
int MaxSubsequenceSum(const int array[], int n){ int thisSum, maxSum, i, j, k; maxSum=0; for(i=0;i<n;++i){ thisSum=0; for(j=i;j<n;++j){ thisSum+=array[j]; if(thisSum>maxSum){ maxSum=thisSum; } } } return maxSum; }
3.使用递归进行程序设计。
最大子序列和可能在三处出现,或者出现在整个输入数据的左半部,或者整个出现在右半部,或者跨越输入数据的中部从而占据左右两部分,前两种情况可以递归求解,第三种情况的最大和可以通过求出前半部分的最大和(包含前半部分最后一项)以及后半部分的最大和(包含后半部分的第一项)而得到,然后将这两个和加在一起。
int MaxSubSum(const int array[], int left, int right){ int maxLeftSum, maxRightSum; int maxLeftBorderSum, maxRightBorderSum; int leftBorderSum, rightBorderSum; int center, i; //基准情况 if(left==right){ if(array[left]>0)return array[left]; else return 0; } center=(left+right)/2; maxLeftSum=MaxSubSum(array, left, center); maxRightSum=MaxSubSum(array, center+1, right); maxLeftBorderSum=leftBorderSum=0; for(i=center;i>=left;--i){ leftBorderSum+=array[i]; if(leftBorderSum>maxLeftBorderSum) maxLeftBorderSum=leftBorderSum; } maxRightBorderSum=rightBorderSum=0; for(i=center+1;i<=right;++i){ rightBorderSum+=array[i]; if(rightBorderSum>maxRightBorderSum){ maxRightBorderSum=rightBorderSum; } } return max(maxLeftSum, maxRightSum, maxLeftBorderSum+maxRightBorderSum);//返回三个数的最大值 } int MaxSubsequenceSum(const int array[], int n){ return MaxSubSum(array, 0, n-1); }
算法时间复杂度为.
4.更为有效的方法,时间复杂度为。
int MaxSubsequenceSum(const int array[], int n){ int thisSum, maxSum, i; thisSum=maxSum=0; maxSum=0; for(i=0;i<n;++i){ thisSum+=array[i]; if(thisSum>maxSum) maxSum=thisSum; else if(thisSum<0) thisSum=0; } return maxSum; }
二. 高效率的取幂运算(计算的时间复杂度仅为
)。
long pow(long x, int n){ if(n==0)return 1; if(n%2==0) return pow(x*x, n/2); else return pow(x*x, n/2)*x; }
当然今天记录的只是递归的一些简单应用,在数据结构树,图等数据结构中有广泛的应用,以后将逐步学习。

浙公网安备 33010602011771号