Self-study Python Fish-C Note14 P50to51

函数 (part 4)

本节主要讲函数 递归

递归 (recursion)

递归就是函数调用自身的过程

示例1:

python 复制代码
def fun1(i):
    if i > 0: 
        print('something')
        i-=1
        fun1(i)
fun1(5) # 这样就会打印五遍 'something'
something
something
something
something
something

要让递归正常工作,一定要有一个结束条件,并且每次调用都会向着这个结束条件去推进。比如上面的例子,加上一个 if 条件语句,让递归在恰当的时候进行回。归小心无限调用的死循环(可以使用 Ctrl + C 强制结束)

有这样一句话"天才程序员用递归,普通程序员用迭代"。接下来我们用几个例子来批判比较一下相同任务递归与迭代的区别:

示例2,求一个数的阶乘:

在数学中,正整数的阶乘(英语:factorial)是所有小于等于该数的正整数的积,记为 n! 例如5的阶乘表示为 5!,其值为120

python 复制代码
# 使用迭代
def fact1(n):
    result = n
    for i in range(1,n):
        result*=i
    return result
print(fact1(5))
print(fact1(10))
print(fact1(1))
120
3628800
1
python 复制代码
# 使用递归
def fact2(n):
    if n == 1:
        return 1
    else:
        return n*fact2(n-1)
print(fact2(5))
print(fact2(10))
print(fact2(1))  
# print(fact2(-1))  这个如果运行会进入无限循环,挂掉
120
3628800
1

以 fact2(5) 为例,代码中实际做的如下:

递归过程 结果
fact2(5) = 5 * fact2(4) ------> fact2(5) = 5 * 4 * 3 * 2 * 1
fact2(4) = 4 * fact2(3) ------> fact2(4) = 4 * 3 * 2 * 1
fact2(3) = 3 * fact2(2) ------> fact2(3) = 3 * 2 * 1
fact2(2) = 2 * fact2(1) ------> fact2(2) = 2 * 1
fact2(1) = 1 ------> fact2(1) = 1

示例3,斐波那契数列:

斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称"兔子数列",其数值为 1,1,2,3,5,8,13,21,34,55,89......这个数列从第3项开始 ,每一项都等于前两项之和。

python 复制代码
# 迭代法
def fib1(n):
    a = 1
    b = 1
    c = 1
    while n > 2:
        c = a + b 
        a = b
        b = c
        n-=1
    return c
print(fib1(1))
print(fib1(2))
print(fib1(3))
print(fib1(4))
print(fib1(5))
print(fib1(6))
1
1
2
3
5
8
python 复制代码
# 递归法
def fib2(n):
    if n==1 or n==2:
        return 1
    else:
        return fib2(n-1)+fib2(n-2)
print(fib2(1))
print(fib2(2))
print(fib2(3))
print(fib2(4))
print(fib2(5))
print(fib2(6))
1
1
2
3
5
8

此时:

调用代码 过程 结果
fib2(1) 直接去到 return 1 1
fib2(2) 直接去到 return 2 1
fib2(3) fib2(3)=fib2(2)+fib2(1)=2 2
fib2(4) fib2(4)=fib2(3)+fib2(2)=fib2(2)+fib2(1)+fib2(2) 3
fib2(5) fib2(5)=fib2(4)+fib2(3)=fib2(3)+fib2(2)+fib2(2)+fib2(1)=fib2(2)+fib2(1)+2*fib2(2)+fib2(1)=5 5
fib2(6) ... 8
... ... ...

如果我们使用递归计算第 120 个数 即 fib2(120), 我们会发现计算了很长时间依然无法计算出结果。反而,使用迭代 fib1(120) 结果计算的很快。这就体现了递归和迭代之间的效率问题。每一次调用递归函数,他并不会立刻返回,而是要等到最底层的那个函数返回,然后在一层一层往上走,这个过程是非常耗费资源的。

汉诺塔

有三根杆子A,B,C。A杆上有 N 个 (N>1) 穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至 C 杆:

(1) 每次只能移动一个圆盘;

(2) 大盘不能叠在小盘上面。

提示:可将圆盘临时置于 B 杆,也可将从 A 杆移出的圆盘重新移回 A 杆,但都必须遵循上述两条规则

python 复制代码
def hanoi(n,x,y,z):
    if n==1:
        print(x,'-->',z) # 如果只有1层,直接将金片从 x 移动到 z
    else:
        hanoi(n-1,x,z,y) # 将 x 上的 n-1 个金片移动到 y
        print(x,'-->',z) # 将放在最下面的金片从 x 移动到 z
        hanoi(n-1,y,x,z) # 将 y 上的 n-1 个金片移动到 z

hanoi(5,'A','B','C')
A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C
A --> B
C --> B
C --> A
B --> A
C --> B
A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C
B --> A
C --> B
C --> A
B --> A
B --> C
A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C

总结递归函数的执行逻辑:递归函数在调用的时候不会直接立刻的去返回,而是经过层层调用,直到遇到符合条件的时候再触发返回机制,接着再逐层的返回。注意,递归函数一定要有一个结束条件

附言:

题目:Self-study Python Fish-C Note-14 P50-P51

本文为自学B站上鱼C的python课程随手做的笔记。一些概念和例子我个人为更好的理解做了些查询和补充

因本人水平有限,如有任何问题,欢迎大家批评指正!

原视频链接:https://www.bilibili.com/video/BV1c4411e77t?p=8

相关推荐
Theodore_10222 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
网易独家音乐人Mike Zhou2 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
安静读书2 小时前
Python解析视频FPS(帧率)、分辨率信息
python·opencv·音视频
----云烟----4 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024064 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
小二·4 小时前
java基础面试题笔记(基础篇)
java·笔记·python
开心工作室_kaic4 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
向宇it4 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
武子康4 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神5 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式