栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

递归函数定义、递归应用案例-科赫雪花/雪花晶片/汉诺塔

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

递归函数定义、递归应用案例-科赫雪花/雪花晶片/汉诺塔

Python基础之递归函数的应用


文章目录
  • 递归的定义
  • 循环和递归的区别
  • 递归函数的实例
    • 科赫雪花
    • 雪花晶片
    • 汉诺塔


递归的定义

函数定义中调用函数自身的方式称为递归。就像一个人站在装满镜子房间中,看到的影响就是递归的结果。
数学上有个经典的递归例子叫阶乘:

	n!=n(n-1)(n-2)......(1)

另一种表达阶乘的方式

		 1   n=0
n!= 
		n(n-1)! otherwise

这个定义说明0的阶乘 按定义是1,其他数字的阶乘定义为这个数字乘以比这个数字小1数的阶乘。递归不是循环,因为每次递归都会计算比它更小数的阶乘,直到0!。0!是已知的值,被称为递归的基例,当递归到底了,就需要一个能直接算出值的表达式。
阶乘的例子揭示了递归的两个关键特征。
(1)存在一个或多个基例,基例不需要再次递归,它是确定的表达式。
(2)所有递归链要以一个或多个基例结尾。
根据用户输入的整数n,计算并输出n的阶乘:

def fact(n):
    if n==0:
        return 1  #当n=0,fact()函数不再使用递归函数,返回值1
    else:
        return n*fact(n-1) #当n != 0,通过递归返回n与n-1阶乘的乘积
num=int(input("请输入一个整数:"))
print(fact(abs(num))) 
--------------------------------------------------------------
输出结果:
请输入一个整数:5
120

递归遵循函数的语义,每次调用都会引起新函数的开始,表示它有本地变量值的副本,包括函数的参数。例如5!的递归调用,每次函数调用时,函数参数的副本会临时存储,递归中各函数再运算自己的参数,相互没有影响,当基例结束运算并返回值时,各函数逐层结束运算,想调用者返回计算结果。

循环和递归的区别

1、利用循环绘制大小不同的五角星。

import turtle
def draw_wjx(size):
    i=1
    while i<5:
        turtle.fd(size)
        turtle.rt(144)
        i +=1
def main():
    turtle.penup()
    turtle.backward(200)
    turtle.pendown()
    turtle.pensize(3)
    turtle.pencolor("red")
    j=200
    while j<=300:
        draw_wjx(j)
        j +=50
    turtle.done()
    
main()

2、利用递归绘制不同大小的五角星

import turtle
def draw_wjx2(size):
    i=1
    while i<5:
        turtle.fd(size)
        turtle.rt(144)
        i +=1
    size+=50
    if size <=300:
        draw_wjx2(size) #递归
def main():
    turtle.penup()
    turtle.backward(200)
    turtle.pendown()
    turtle.pensize(3)
    turtle.pencolor("red")
    draw_wjx2(200)
    turtle.done()
    
main()

总结:循环和递归的区别
循环由已知推未知,不断向后。
递归由未知寻找已知,不断向前,递归的实质是出入栈,效率较低。

递归函数的实例 科赫雪花

科赫雪花绘制方法:
(1)正整数n代表科赫雪花的阶数,表示生成科赫雪花过程的操作次数。科赫雪花初始化阶数为0,表示一个长度为L的直线。
(2)将直线L等分成3段,每段长度为L/3。
(3)中间一段用边长为L/3的等边三角形的两个边代替,这样得到1阶的科赫雪花曲线。
(4)重复前面(2)(3)的操作。

import turtle
def draw_koch(size,n):
    if n == 1:
        turtle.fd(size)   #  1阶的科赫雪花曲线就是一条直线
    else:
        for angle in [0,60,-120,60]:  # turtle在“尖”的四条线上改变的角度,分别为0°,60°,-120°,60°
            turtle.left(angle) # 对应上边四个角度,一共需要转4次弯,画出本阶的四条线,
            draw_koch(size/3,n-1)# 每个角度下的一个边,对应低一阶的科赫雪花曲线的“尖”;

def main():
    turtle.setup(800,400)
    turtle.speed(0)
    turtle.penup()
    turtle.goto(-300,-50)
    turtle.pendown()
    turtle.pensize(2)
    draw_koch(200,4)
    turtle.hideturtle() #将光标隐藏
    
main()

输出结果

前面的代码只是完成一个由“尖”组成的“边”,并不是完整的科赫雪花曲线。
完整的科赫雪花曲线由3个“边”组成,转动120度,使得科赫雪花曲线能围城一个三角形,形成最终的科赫雪花效果。

import turtle
def draw_koch(size,n):
    '''科赫曲线--一个由“尖”组成的“边”'''
    if n == 1:
        turtle.fd(size)
    else:
        for angle in [0,60,-120,60]:
            turtle.left(angle)
            draw_koch(size/3,n-1)
def draw_into():
    '''画笔初始化'''
    turtle.setup(600,600)
    turtle.speed(0)
    turtle.penup()
    turtle.goto(-200,100)
    turtle.pendown()
    turtle.pensize(2)

def main(size,n): 
    '''完整的n阶科赫雪花曲线'''
    draw_into()
    draw_koch(size,n)  # 完整的科赫雪花曲线由3个“边”组成。
    turtle.right(120)#转动120度,使得科赫曲线能围城一个三角形,形成最终的科赫雪花
    draw_koch(size,n)
    turtle.right(120)
    draw_koch(size,n)
    turtle.hideturtle()
    
main(400,5)

输出的结果

根据科赫雪花绘制的方法绘制雪花晶片

雪花晶片


(1)当阶数为1时,画出一条直线L。
(2)当阶数大于1时,先将直线二等分,即L/2,左转60度,画出长度L/3的直线,再沿着直线移动-L/3长度回到二等分的位置,再左转-120度,画出长度L/3的直线,再沿着直线移动-L/3长度回到二等分的位置,最后左转60度,再进行二等分。

import turtle
def draw_snow(size,n):
    if n == 1: 
        turtle.fd(size)  #当n=1阶时,绘制直线
    else:
        draw_snow(size/2,n-1) #当n>1阶时,将直线进行二等分 
        for  angle in [60,-120]:
            turtle.left(angle)# 左转60度,画出长度L/3的直线,再沿着直线移动-L/3长度回到二等分的位置,
            draw_snow(size/3,n-1)
            turtle.fd(-size/3)
        turtle.left(60) #最后左转60度
        draw_snow(size/2,n-1) #再进行二等分
def draw_into():
    '''画笔初始化'''
    turtle.setup(600,600)
    turtle.speed(0)
    turtle.penup()
    turtle.goto(0,0)
    turtle.pendown()
    turtle.pensize(2)
    turtle.left(90)
    
    
def main(size,n):
    draw_into()
    draw_snow(size,n)
    turtle.hideturtle()
    
main(200,5)

输出结果:

绘制6片晶片形成完整的晶片雪花效果

import turtle
def draw_snow(size,n):
'''绘制晶片'''
    if n == 1:
        turtle.fd(size)
    else:
        draw_snow(size/2,n-1)
        for  angle in [60,-120]:
            turtle.left(angle)
            draw_snow(size/3,n-1)
            turtle.fd(-size/3)
        turtle.left(60)
        draw_snow(size/2,n-1)
def draw_into():
    '''画笔初始化'''
    turtle.setup(600,600)
    turtle.speed(0)
    turtle.penup()
    turtle.goto(0,0)
    turtle.pendown()
    turtle.pensize(2)
    turtle.left(90) #将画笔朝上
    
    
def main(size,n):
    draw_into()
    i=1
    while i <=6: #绘制6片晶片
        turtle.goto(0,0) #每次回到原点位置绘制
        draw_snow(size,n)
        turtle.right(60) #每片晶片的角度60度,绘制6次,形成完整的雪花晶片
        turtle.hideturtle() #每片绘制完将光标隐藏
    turtle.done() #结束绘制
    
main(200,5) #直线长度为200, 5阶的雪花晶片

输出结果

汉诺塔

汉诺塔源于真实的故事,在世界某个地方有个很虔诚的宗教组织,期中僧侣维护着一项神圣任务:保持宇宙时间。在时间的最开始,僧侣在平台上竖立了3个垂直杆,在最左侧上有64个不同半径的金色同心圆盘,直径较大的圆盘堆放在下方,形成金字塔样的整体外观,僧侣们的任务是将有所圆盘从最左侧杆子移动到最右侧杆子,这个宗教认为当僧侣们完成任务的时候,万事万物将会化为乌有,宇宙结束。为了保持神圣的顺序,僧侣们移动圆盘需要尊从特定的规则,一次只能移动一个盘子,盘子只能在3个杆子之间移动,更大的盘子不能放在更小的盘子上面。
实现把 A 的 n 个盘子移动到 C(盘子编号是 [1, n] ),要求每次只能移动1个盘子,大盘子只能放在小盘子下面。
1、1个盘子移动时

直接从A移到C上
2、2个盘子移动时

此时借助中间B杆子,盘子1移到B杆子,盘子2移到C杆子,再将B杆子中的盘子1移到C杆子上。即A->B,A->C,B->C。
3、3个盘子移动时

借助中间B杆子,盘子1从A杆移到C杆子,盘子2从A杆移到B杆,再将盘子1从C杆移到B杆中,将盘子3从A杆移到C杆,将盘子1从B杆移到A杆,将盘子2从B杆移到C杆,最后将盘子1从A杆移到C杆。即A->C,A->B,C->B,A->C (此时最大的盘子已经移动到C。接下来剩下的要从B经过A(新的过度柱)移动到C,即B->A,B->C,A->C。
4、思路
(1)当 n == 1时,直接将盘子从 A 移动到C
(2)当 n > 1时,可以拆分成3大步骤
①将 n– 1 个盘子从 A 移动到B,可以利用递归调用

②将编号n最大的盘子从A移到C

③ 将编号n-1的盘子从B移到C,可以利用递归调用

def hanoi(n,A,B,C):         #定义汉诺塔函数,参数n是圆盘数,A、B、C是3根柱
    if n==1:                 #判断圆盘数,如果等于1,递归条件
        print("第{}个盘子从{}---->{}".format(n,A,C))   # 直接将A柱上的圆盘移动到C柱上
    else:  #否则,进行递归移动
        hanoi(n-1,A,C,B)  #递归将A柱最上方的n-1个盘子落在B柱
        print("第{}个盘子从{}---->{}".format(n,A,C))     # 将最大的盘子移到C柱上
        hanoi(n-1,B,A,C)  #递归将B柱上的n-1个盘子,移到C柱上
        
hanoi(3,'A','B','C')               #调用函数

第1个盘子从A---->C
第2个盘子从A---->B
第1个盘子从C---->B
第3个盘子从A---->C
第1个盘子从B---->A
第2个盘子从B---->C
第1个盘子从A---->C

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/977429.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号