递归的参数和返回值

时间:2022-12-06 00:26:41

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