递归
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
递归函数特性:
1.必须有一个明确的结束条件;
2.每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3.相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入)。
4.递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
例一:计算1到100之间所有数之和:
def mm(n):
if n==1:
return 1
return n+mm(n-1)
print(mm(100))
#结果得到5050
如上函数在n不等于1的情况下一直调用函数自身,使得从100开始每一个数(n-1)都相加,直到n=1时,前面数相加之和再加上1并返回了这个值。
例二:斐波那契数列,求第20个数的值:
def fbnq(n):
if n ==2 or n==1:
return 1
return fbnq(n-2)+fbnq(n-1)
print(fbnq(20))
#输出结果6575
斐波那契数列为1,1,2,3,5,8........规律为第三数为前两项之和,第一项与第二项为1。所以我们直接一直调用函数n-1与n-2相加,直到n=1为止,得到所要的数。
例三:阶乘:
def fact(n):
if n==1 or n==0:
return 1
return n * fact(n - 1)
print( fact(5))
#5的阶乘为120
一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。如上函数即为不停调用n乘以函数(n-1)得到所需阶乘。
例四:一条直线可将一张纸划分为2块区域,2条可划分最多4块,3条最多7块,四条最多11块,求问100条线最多可划分几块?
def o(n):
if n==1:
return 2
return n+o(n-1)
print(o(100))
#最多可划分5051
数列的为2,4,7,11,16.......规律为第n个数等于第n-1个数加n。
所以我们只需不停的调用n+函数(n-1),直到n等于1时,将返回的2相加,即可得到第n个数的值。
例五:随机输入一个正整数,组成一个从1到n的数列,组成一个圈,然后将下标为3的倍数的数删除,求最后剩下的数字:
a=int(input('请输入一个正整数:')) #将输入的字符串转成int类型
b=[x for x in range(1,a+1)]
count=0
while True:
if len(b)==1:
print('结束')
break
count += 1
if count%3==0:
b.pop(0)
else:
b.append(b.pop(0))
print(b) #将每一步的步骤打印,更直观的看见函数怎样运行
print(b)
首先输入一个整数,并转为int类型,然后遍历(1,n+1),组成一个列表,设置一个count变量,为0.然后开始循环,首先设置结束条件,当列表长度为1时,结束循环,将列表打印;然后将count+=1,并判断count是否能被3整除,如果能,则将现在列表中第一个数删除,如果不能,则删除列表第一个数,再将删除的这个数添加到列表最后面,这就形成了一个圈。
例六:二叉树
二叉树是树的特殊一种,具有如下特点:
1、每个结点最多有两颗子树,结点的度最大为2。
2、左子树和右子树是有顺序的,次序不能颠倒。
3、即使某结点只有一个子树,也要区分左右子树。
简单的做一个练习:输入一组数字,通过二叉树的形式储存,并将其由大到小的输出:
#usr/bin/python
#-*-coding:utf-8-*-
class Tree():
root=None
class Node():
data=None
left=None
right=None
def zhongxu(self):
if self.left is not None:
self.left.zhongxu()
print(self.data)
if self.right is not None:
self.right.zhongxu()
def add(self,node):
if self.data > node.data:
if self.left is None:
self.left=node
else:
self.left.add(node)
if self.data < node.data:
if self.right is None:
self.right=node
else:
self.right.add(node)
def zhongxu(self):
self.root.zhongxu()
def add(self,data):
node=self.Node()
node.data=data
if self.root is None:
self.root=node
else:
self.root.add(node)
if __name__=='__main__':
tree=Tree()
tree.add(22)
tree.add(4)
tree.add(555)
tree.add(23)
tree.add(31)
tree.add(12)
tree.add(76)
tree.add(57)
tree.zhongxu()
首先我们创造了一个类Tree,首先定义了一个root(根)为None,在里面又创造了一个类Node,在其中定义了三个对象,data,left,right都为None;然后在Tree中写一个方法add,在这个方法中,需要输入一个参数data,定义了一个node对象,但是这个对象取Node类,这个node对象的data为我们输入的data参数,接着判断当前的root是否为None,如果是,则root赋值为node,如果不是,则再当前的root后add输入的node,接着我们返回类Node,data的值在上一步以被赋值为我们输入的data,接着写一个方法add,判断当前的data(node.data)与原来的data(self.data)比较大小,如果小于原来的data,则判断left是否为空,空则赋值给left,否则再left后添加data;如果大于则与left相同,判断right,这样我们数据就存储在数树中。
接着我们在Tree中写一个zhongxu的方法,里面调用当前root的zhongxu ,我们返回类Node,写一个方法zhongxu,在这个方法中,我们判断每个在树中的数据left是否为空,否则继续判断这个数据left的数据的left是否为空,一直循环,直到left为空,然后将这个数据输出,接着判断输出的这个数据的right是否为空,是则对这个right的值再进行这样一个循环,直达将整租数输出。
上述程序输出如下:
4
12
22
23
31
57
76
555