深入理解递归(一)

本文深入探讨递归的概念,从迭代与递归的区别开始,阐述如何思考递归,通过Paul Graham的方法解释递归的正确思考方式。接着,介绍了递归的实现,包括递归模板和递归在汉诺塔问题及二叉树节点计数问题中的应用。讨论了何时使用递归以及使用递归的注意事项,并总结了递归的优点和缺点,以及它在分治法、动态规划和回溯算法中的应用。
摘要由CSDN通过智能技术生成

内容会持续更新,有错误的地方欢迎指正,谢谢!

什么是迭代和递归

迭代的是人,递归的是神。 –L. Peter Deutsch

简单的定义: 当函数直接或者间接调用自己时,则发生了递归。但递归并不直观, 也不符合我们的思维习惯。因为递归的过程就是出入栈的过程。所以,每个递归程序都可把它改写为非递归版本,只需利用栈,通过入栈和出栈两个操作就可以模拟递归的过程,比如:二叉树的遍历。

如何思考递归

例子:
n的阶乘

int func(int n)
{
    if(n<=1)
    {
        return 1;
    }
    return n*func(--n);
}

我们习惯的思维是:已知Factorial(0),乘上 1 就等于Factorial(1),再乘以 2 就等于Factorial(2),,,直到乘到 n。而递归和我们的思维方式正好相反。那我们怎么判断这个递归计算是否是正确的呢?

Paul Graham提到一种方法, 算是递归正确的思考方式,该方法如下:
1. 当n=0, 1的时候,结果正确。
2. 假设函数对于n是正确的,函数对n+1结果也正确。
如果这两点是成立的,我们知道这个函数对于所有可能的n都是正确的。

其实就是数学归纳法,第 1 点称为基本情况,第 2 点称为通用情况。最重要的是第1点,如果我们去掉if(n<=1)这个基本情况后, 代码会进入死循环,永远不会结束,所以,把第 1 点称为终止条件。

递归的实现

递归的模板:

void f()  
{  
     if(符合边界条件)  
    {  
       ///////  
        return;  
    }  

     //某种形式的自调用  
     f()
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值