谈谈如何阅读递归代码

谈谈递归

一,谈谈新手对递归的困惑

在新手学习编程语言的过程中,递归其实是绕不开的一个坎,包括我在内的大部分人在最初学习递归的时候都很困惑,很难理解他的执行流程,简简单单的几行代码却让人抓不着头脑,因此,本人想在这发表一些自己的愚见。

本文着重讲解的是递归的执行流程以及如何理解递归代码,而并非如何使用递归解决问题

二,递归与二叉树

对于大部分人来说,第一次遇到递归,都是从斐波那契数列开始的,但是,笔者认为,他对于新手而言,并不是最好的模型,因为它涉及到递归结果相加。因此,笔者认为二叉树才是理解递归最好的模型!!!首先我们来看一颗简简单单的二叉树(只能向下不能回头):

D:\C\fb.c

首先,我们可以尝试下竖着遍历上面这颗树。即为

横向的遍历一颗树,就是理解递归总框架的重点!!!

对于递归来讲,所谓的递,就是向下纵深的过程,对于归,就是碰到叶子节点的子(null)继而返回! 

带着这样的思路,来看一段代码

//伪代码
void printTree(Tree treenode){
    if(treenode==null) return;

    printf("打印该节点");
    printTree(treenode->lchild);//遍历左子树
    printTree(treenode->rchild);//遍历右子树
}

由于是为了方便理解递归的写作,因此不去思考如何使用递归实现树的遍历。

对于递归的阅读

a.首先是查看递归的“归”,在这里,即节点为空的时候返回

b.然后,我们可以发现,是先执行左子树,再执行右子树(顺序非常重要)

因此在第一次到达“归”的时候,代码的执行结果是:

 对于阅读递归,他的第一次执行结果非常简单,但对于我们破解递归非常重要!

由于每次进入方法,在判断不是“归”我们都直接输出,即输出4 2 1;

对于1节点的理解尤为重要,当执行到1节点之后,代码继续向左纵深,但1的左节点为空,因此返回;

c.对于执行到第一次归为止,我们可以看出结论:对于右节点的访问还未开始!因此,对于4,2,1三个节点的代码

 printTree(treenode->lchild);//4 2 1三个节点代码的执行都卡在了当前位置!!!

d.随后1开始向右纵深,但右节点为空,则返回,1节点代码彻底结束!开始2的向右纵深!

e,由于2的右节点为3因此输出,此时输出结果为(4 2 1 3)

f,由于3节点的代码刚刚开始,则开始第二轮的向左纵深,由于3左右均无孩子,他的左右纵深都执行到“归”,因此3节点代码运行结束返回到父节点2

g,此时2的代码结束返回到4,4开始向右纵深

……

因此最终结果为4 2 1 3 5

三,递归与栈

递归的执行是离不开栈的,所谓的栈可以理解为一个长长的袋子,你不断往它放物品,但你只能拿出最靠袋口的物品(先进后出)。

继续用栈来理解上面的代码和树。

a.依旧最先理解第一次执行到归,此时的栈结构是

由于在执行递归前就输出,因此他们虽然还在栈中,但他们都已经打印输出

b.1的左右都没节点,因此方法执行结束,1调离栈

c.而2的右节点存在,则将其入栈输出

之后同理可得……

因此上述代码可以使用栈来实现,而非递归,并且通常来讲会更好,因为当递归层数过高时,系统栈容易溢出。

 举例:

用上述代码模拟

系统栈中的情况为

由于每次进栈就输出,因此输出结果为 4 2 1 3 6 5 7,即树的前序遍历

 

四,回到斐波那契

#include<stdio.h>

int fib(int number){
    if(number==1||number==2){
        return 1;
    }
    return fib(number-1)+fib(number-2);
}

int main(){
    printf("%d",fib(6));
}

回到最初的斐波那契,我们以输入5为例子

1.首先判断它“归”的条件,即当想要进入栈的数字为2或者1,则直接输出结果1,不进入栈。

2.由于return fib(number-1)+fib(number-2)中,是先(number-1进入递归),因此,我们可以获得遇到第一次遇到“归”的结果,并将其画为树!

3.此时5 4 3 的代码都只执行到了结果相加的前半部!! 而f(2)返回1,因此f(3)倍加数为1,此时执行f(3-2)

4.因为f(3-2)为f(1),因此直接返回1,则f(3)的结果为1+1=2,将结果为2作为f(4)的被加数继续执行

4.重复该过程,可以得到一颗对应的二叉树

最终结果为5

由于是第一次写文章,难免有描写不当的地方

v1.0

 

  • 11
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值