小甲鱼Python学习笔记之函数(三)

本文探讨了递归的概念,强调了递归的两个关键特点:调用自身和结束条件。通过实例展示了如何使用递归和循环迭代实现斐波那契数列,并讨论了递归效率问题。此外,还介绍了用递归解决经典问题——汉诺塔的算法步骤。最后,提到了不同方式实现斐波那契数列,包括闭包和生成器。
摘要由CSDN通过智能技术生成

定义

函数之间是可以相互调用的,而递归就是函数调用自身的过程。

>>> def funA():
	print("Love")

	
>>> def funB():
	funA()

	
>>> funB()    //函数的间接调用
Love
>>> def func(n):
	if n>0:       //递归调用一定要有结束条件!!!
		print("I Love Python")
		n-=1
		func(n)   //递归,函数调用自身

		
>>> func(5)
I Love Python
I Love Python
I Love Python
I Love Python
I Love Python

递归的两个特点(重中之重!!!)

  • 调用自身
  • 结束条件

递归的应用

能够用递归实现的功能都能够用循环迭代来实现

求一个正整数的阶乘

>>> def factIter(n):   //使用循环迭代实现一个正整数的阶乘
	result=n
	for i in range(1,n):
		result *= i
	return result

>>> factIter(5)
120
>>> factIter(10)
3628800
>>> def factRecur(n):     //使用递归实现一个正整数的阶乘
	if n==1:
		return 1
	else:
		return n*factRecur(n-1)


>>> factRecur(5)
120	

用递归实现斐波那契数列

起源
假设有一对兔子在两个月大的时候才有繁殖能力,接下来每个月都生出一对兔子宝宝,如果假设所有的兔子都不会老去,那么一年后会繁殖出多少对可爱的兔子来呢?
如果在年初种下一对兔子,就可以在年底收获144对美味的兔头,
在这里插入图片描述
代码的具体实现如下

>>> def fibIter(n):            //用循环迭代的方式实现斐波那契数列
	a=1
	b=1
	c=1
	while n>2:
		c=a+b
		a=b
		b=c
		n-=1
	return c

>>> fibIter(12)
144
>>> def fibRecur(n):         //用递归的方式实现斐波那契数列
	if n==1 or n==2:
		return 1
	else:
		return fibRecur(n-1)+fibRecur(n-2)

	
>>> fibRecur(12)
144
>>> 

Q:递归的效率问题

用其他方式实现斐波那契数列

用闭包实现斐波那契数列

(待更新,,,求大神评论区提供一下)
用生成器实现斐波那契数列

  • 传参
>>> def fibs(n):
	a=0
	b=1
	while n>0:
		a,b=b,a+b
		n-=1
		yield a

		
>>> list(fibs(12))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
  • 不传参
>>> def fib():
	a=0
	b=1
	while True:
		a,b=b,a+b
		yield a

		
>>> for i in fib():
	if i<100:
		print(i)
	else:
		break

	
1
1
2
3
5
8
13
21
34
55
89

用迭代器实现斐波那契数列

  • 传参
>>> class Fib:
	def __init__(self,n=20):
		self.a=0
		self.b=1
		self.n=n
	def __iter__(self):
		return self
	def __next__(self):
		self.a,self.b=self.b,self.a+self.b
		if self.a>self.n:
			raise StopIteration
		return self.a

	

执行结果

>>> fibd=Fib()
>>> for i in fibd:
	print(i)

	
1
1
2
3
5
8
13
>>> f=Fib(n=100)
>>> for i in f:
	print(i)

	
1
1
2
3
5
8
13
21
34
55
89
  • 无参
class Fibs:
	def __init__(self):
		self.a=0
		self.b=1
	def __iter__(self):
		return self
	def __next__(self):
		self.a,self.b=self.b, self.a+self.b
		return self.a

	
>>> f=Fibs()
>>> for i in f:
	if i<20:
		print(i)
	else:
		break

	
1
2
3
5
8
13

用递归实现汉诺塔

起源

汉诺塔在1883年时由法国数学家卢卡斯发明的,该数学问题与一个印度传说有关,据说在世界中心贝拿勒斯的圣庙里有一块黄铜板,上面插着三根宝针,印度教主神梵天在创造世界的时候,在其中的一根针上从上往下穿好了由大到小的64枚金片,这就是汉诺塔的原型。有一个僧侣没日没夜的移动,当所有的金片都移动到另外一根针上的时,世界就会在一声霹雳中消灭,梵塔和众生也都将同归于尽。在这里插入图片描述

规则

  1. 一次只能移动一枚金片
  2. 无论在哪根针上,小片必须在大片的上面

抽象为数学问题
如下图所示,从左到右有A、B、C三根柱子,其中A柱子上面有从小叠到大的n个圆盘,现要求将A柱子上的圆盘移到C柱子上去,期间只有一个原则:一次只能移到一个盘子且大盘子不能在小盘子上面,求移动的步骤和移动的次数
在这里插入图片描述
解:

  • n 为1
          第1次 1号盘 A---->C        sum = 1 次
  • n 为2

         第1次 1号盘 A---->B
         第2次 2号盘 A---->C
         第3次 1号盘 B---->C        sum = 3 次

  • n 为 3
           第1次 1号盘 A---->C
           第2次 2号盘 A---->B
           第3次 1号盘 C---->B
           第4次 3号盘 A---->C
           第5次 1号盘 B---->A
           第6次 2号盘 B---->C
           第7次 1号盘 A---->C        sum = 7 次

规律:
         1个圆盘的次数  2的1次方减1
         2个圆盘的次数  2的2次方减1
         3个圆盘的次数  2的3次方减1
          。 。 。 。 。
         n个圆盘的次数   2的n次方减1

算法步骤分析:

实现这个算法可以简单分为三个步骤:

  • 把n-1个盘子由A 移到 B;
  • 把第n个盘子由 A移到 C;
  • 把n-1个盘子由B 移到 C;

从这里入手,在加上上面数学问题解法的分析,可以发现

  • 把A上n-1个盘子通过借助辅助塔(C塔)移到了B上,
  • 把最大的一个盘子由A移到C上去;
  • 把B上n-1个盘子通过借助辅助塔(A塔)移到了C上;

代码实现如下:

def hanoi(n,x,y,z):
    if n== 1:
        print(x,'-->',z)  # 只有一层,直接将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

n=int(input("请输入汉诺塔的层数:"))
hanoi(n,'A','B','C')

执行结果如下:
在这里插入图片描述
参考:
Python实现斐波那契数列.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值