教你彻底学会递归——《入门篇》

一、递归的基本思想

1.什么是递归

对于递归这样的一个基本的算法而言的话呢在程序设计当中, 其实它就是一个函数,在这个函数当中直接或者间接的调用其自身。 这样的表现形式或者说一种操作的方式呢,我们就称之为叫做递归。
那么递归呢可以看成它就是一个问题求解的那么一个过程。 我们将一个复杂的大的问题呢,划分成许多相同性质的小的子问题。
对于一个复杂大的问题来讲,你可能是不好求解的。但是其中的一些小的子问题呢是比较容易进行求解。 那么这一些小的子问题的解最后呢就构成了原问题的解。

2.总体思想

将待求解的问题转变成一个输入变量x的函数f(x)
然后通过去寻找函数g(x),使得f(x)=g(f(x-1)),我们递归求解的过程其关键就是去找寻这个函数g( )
f(x) 可以转化为 g() 这个函数,而 g() 这个函数的这个输入的这个变量是什么呢?是 f(x-1) 所以我们看到通过这样的一个递归表达式,我们就可以有效的把 f(x) 这样的一个规模的一个问题转化为变成一个 f(x-1) 这样一个规模的子问题。 就是,原问题被划分成了更小规模的问题。
然后且我们已知到f(0)的值,就可以通过f(0)和g()求出f(x)的解了。

3.推广

所谓推广就是扩展到多个输入变量x,y,z等,就是我们可以将包含若干个输入变量比如说 x、y、 z, 同时也可以对递归表达式中间的这个不断递归的这个过程x-1推广到至x-x1 ,也就是说去减去某一个具体的量。 那么只要保证递归本身这个算法它是朝着出口的方向即可。
所谓出口就是指说是朝着这个递归结束的方向来进行,你不能进行一个死循环或者是 一直在一个嵌套递归的当中。

二、递归与枚举的区别

枚举:
把一个问题划分成一组子问题,依次对这些子问题求解,子问题之间是相互独立的,是横向的,同类的关系
递归:
把一个问题逐级分解成子问题,子问题与原问题之间是相互联系的,纵向的,同类的关系
语法形式上:在一个函数的运行过程中,调用这个函数本身分为直接调用和间接调用。
直接调用:在fun()中直接执行fun()
间接调用:在fun1()中执行fun2();在fun2()中又执行fun1()

三、递归的三个要点

1.递归式

如何将原问题划分为子问题?
也就是上面讲到的如何将f(x)问题转化为一个关于f(x-1)的表达式
也就是说你怎么样能把一个 x 规模的一个问题, 化简为一个 x-1 规模的一个问题。

2.递归出口

递归出口的条件,即最小子问题的求解,可以允许多个出口。

3.界函数

问题规模的变化函数我们称做为界函数。
问题规模变化的函数,它保证递归的规模向出口条件靠拢。
也就是说你的这个不断变化的这个函数是不断的向出口逼近的,而不是说你的这个问题的规模越来越 多或者说走向一个相跟你这个递归本身这个出口相背离的方向。

四、求阶乘的递归程序

我们一般求解阶乘首先想到的都是用循环语句实现:

#python
n = int(input()) #给定n
m = 1			#阶乘n的初始值
for i in range(1,n+1):  
    m *= i 		
print(n,"的阶乘是%d" % m)

现在我们运用递归的思想来求解阶乘的问题:
n! = n*(n-1)(n-2)*…*2*1=n(n-1)!=n*(n-1)*(n-2)!=…由此类推
相信大家应该已经都看懂了
因此我们写出下面代码

#python
def Factorial(n):  # 给定n
    if n == 0:    # n为1是返回1
        return 1
    else :
        return n*Factorial(n-1)  #进行n的阶乘,划分成子问题求解

用n=4来看看它的每一步:(先红色箭头进入,到绿色箭头一步步输出到最终结果)
在这里插入图片描述

五、递归解决问题的关键

关键就两部分:
1.找出递推公式
2.找到递归终止条件
注意事项:
由于函数的局部变量是存在栈上的,如果有体积大的局部变量,比如数组,而递归层次可能深入的情况下,也许会导致栈溢出
因此可以考虑使用全局数组或动态数组分配数组

递归一共有两篇,下一篇我将用实例来更深入的讲解递归

上一篇文章———>Python正则表达式详解
下一篇文章———>教你彻底学会递归——《进阶篇》

发布了14 篇原创文章 · 获赞 16 · 访问量 497

猜你喜欢

转载自blog.csdn.net/weixin_43347550/article/details/105175959