一个函数只能有一个返回值,具有返回值的递归函数若平行的多次调用自身,那么将会产生多个返回值,这是一个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 }