初步简单地理解递归

         网上有很多关于递归的比喻和例子,比如俄罗斯套娃、德罗斯特效应,这可以给我们一个递归的初始印象,但对于计算机怎么执行递归的逻辑和方式我们还是很迷,毕竟编程是需要的是用计算机的思考模式解决现实中的问题。

       以下是我个人对递归的粗浅理解,在被分治法,动态规划和树图遍历这些有用到的递归的算法折磨得欲仙欲死后,还是回过头来把递归好好地啃透鄙视


        递归,就是在运行的过程中调用自己,是在函数的定义中使用函数自身,这定义一听就很迷,

     我们会有这些疑问:

     什么问题才要用这种听上去就很绕很迷的方法? 怎么调用自身?这样的调用有什么条件?

     这也是我刚接触递归时的疑问,下面我会一一解决这些疑问。


下面先用一个程序示例来让我看看程序中的递归实现:

解决问题:计算一个正整数n的阶乘

阶乘的递归公式:


using System;
using System.Collections.Generic;
namespace 递归
{
    class Program
    {
        static void Main(string[] args)
        {
            int resultNum = JieCheng(5);    //计算5的阶乘
            Console.WriteLine("阶乘的结果为:" + resultNum);  //控制台输出结果

            Console.ReadKey();
        }
        //阶乘实现方法
        static int JieCheng(int n)
        {
            if (n <= 1)
                return 1;
            //实现递归
            int result = n * JieCheng(n - 1);
            //控制台输出
            Console.WriteLine("递归的num为{0},结果为:{1}", n, result);

            return result;
        }
    }
}

我用的是C#写的,实现过程有点语言基础的应该能理解。

控制台输出如下:


        这个结果我想与很多人一开始预想的输出顺序可能不太一样,我们可以看出,递归计算阶乘直接从最小值往上相乘,接下来让我仔细地分析下这个实现方法。


该方法是有返回值的,当我们输入5进人该方法时,方法下的第一句就是判断返回条件,记住,这也是递归的终止条件,接下来就是关键了,我们用一条语句就实现了阶乘的计算,但就是这一句让我在今后很多次怀疑人生发火

int result = n * JieCheng(n - 1);  --递归调用自身,在这里实现俄罗斯套娃,直到出现终止条件返回

下面用图来解释:



图画得有些粗糙,不过应该将过程描述清楚了,想要计算5的阶乘,递归第一件想干的事就是用5乘4的阶乘,可是4的阶乘也不知道,于是为了求4的阶乘,递归想要用4乘3的阶乘,嗯,3的阶乘也不知道,总之递归也很郁闷,我要求谁谁都不知道,好吧,我就一直往下走了,总该有个知道的吧安静,终于找了,递归的使用者让他知道了1的阶乘就是1,也就是我们设置的返回条件,这下递归终于有出头之日了,他利用1的阶乘回过来乘2得到了2的阶乘,依次往上最终回到源头5乘4的阶乘,将结果返回给我们,真不容易啊。

举个生活中的例子,当你进入电影院找了一个位置坐下,你想知道自己坐在哪一排,可你又不想数,于是你问前一排的人,问他是第几排(为自己的智慧和偷懒鼓掌得意),前一排的哥们也不知道,同时他也从你身上看到了智慧的光芒,于是他也问他前一排的人,但他前一排的人干了和你样的事,于是这荒唐的做法一直向前传递,直到第二排的哥们问了下第一排的人,第一排的人虽然觉得这个问题实在是智障,但他给出了答案,好了现在第二排知道了自己的排数,那他可以通知第三排,第三排知道了,通知第四排 . . . . . .终于通知到你了,你一脸复杂看着前排那哥们给你汇报他的排数,心想一群智障。

      结合上面的解释是不是对递归有些理解了,不过也仅仅是知道递归的调用顺序和嵌套关系,下面介绍递归用来解决什么问题。

      从上面的例子可以看出,递归可以将规模大的问题转化成解决方法相似的小问题,从阶乘问题来看,当你要求n的阶乘时,他的解决方法都是当前值乘前一个值的阶乘,最终递归会不断地递进,只要满足终止条件,一般阶乘的终止条件就是n=1,这样从从1~n中间所有的阶乘都可以求得,自然n的阶乘也可以得到。

      使用递归可以让程序简洁,思路清晰,富有逼格,但开销太大,能不用就不用,但在一些特定的问题上使用递归是很有效且易于描述理解的,如树、图的遍历,分治法,斐波那契数列,汉诺塔问题等,这些数据结构和算法用递归是再合适不过了。


最后总结下使用递归的注意点

         1.一定要为递归设置终止条件,同时也要注意终止时的处理方案,不然他会无限循环执行下去;

         2.使用递归远比使用循环的开销要大,尽量不要使用,除非只能用递归或对应的特定问题

         3.将大问题拆解成小问题时,要注意两者直接的解决方法要大致相似或基本一致,在此过程中提取重复逻辑,精简共同的解决方法




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值