一个函数只能有一个返回值,具有返回值的递归函数若平行的多次调用自身,那么将会产生多个返回值,这是一个bug。在树形多分枝结构的递归中对两种方式进行比较讨论。
例如求树高的两种写法:
1 struct Node{
2 int val;
3 Node* child;
4 Node* sibling;
5 Node(){
6 child=NULL;
7 sibling=NULL;
8 }
9 };
10 int height(Node *root){
11 if(root){
12 int maxh=0;
13 for(Node *p=root;p;p=p->sibling){
14 int tmp=height(p->child);
15 if(maxh<tmp){
16 maxh=tmp;
17 }
18 }
19 return maxh+1;
20 }
21 return 0;
22 }
1 int maxh=0;
2 void height(Node *root,int h){
3 if(root){
4 for(Node* p=root;p;p=p->sibling){
5 height(p->child,h+1);
6 }
7 }else{
8 if(maxh<h){
9 maxh=h;
10 }
11 }
12 }
前者使用带有返回值的递归形式,利用返回值进行计算;后者采用传参的形式,利用参数进行计算。之所以能有这两种写法,是因为树高要求每条路径的最深,再进行比较,是到最深处才能确定的。也是唯一的解。而其除了这些有唯一解的递归问题,例如递归建立二叉树的多分枝层次问题等,就很难使用带有返回值的递归求解。带有返回值的递归,由浅入深,在最深处达到出口进行计算后能逐层返回浅层。注意返回,这就需要返回一个唯一确定的值了。
p.s.说明一下何为唯一,递归到最深层后,逐层向浅层返回值,必有确定的一条路径,称为唯一。
一个关键性的点--具象的多分枝递归是一个怎样的过程,前面的文章中提到过多分枝的递归问题生成树形结构。故具体的可以参考图的深度优先遍历,递归是以一条路走到黑,走不动再返回分岔口再选择另一条路,最终遍历多分枝的所有路径的方法,类似我们走迷宫的暴力解法。每条路径不能直接进行传值等交互操作但是,但我们可以选择路径,选择符合我们条件的路径的结果。对比于图的广度优先遍历,可以说深度,也就是递归的方式是一个线性化的路线,只能父子节点进行交互,兄弟节点在不同的路径上故被隔离了;而层次遍历则一次可以访问所有的节点,也就产生了兄弟节点的关联。
下面讨论刚才提到的难以写成带有返回值的递归的问题。
多分枝层次问题:
建立树,例如二叉树有两种形式,一种是层次建立,不在本次递归的主题中讨论;另一种是递归建立,对于每个节点,先建立根节点,再建立左右子树。算法生成的树的顺序即和先序遍历相同,也是“线性”地产生了二叉树。这个多分枝问题直到最深处二叉树建立完毕就结束了,并没有向浅层返回的确定的路径(值。
addition:求树的路径数(二叉树,树自己写循环
1 int paths(node root){
2 if(root!=null){
3 if(root.left==null&&root.right==null)
4 return 1;
5 return paths(root.left)+ paths(root.right);
6 }
7 return 0;
8 }