递归函数

描述:

如果一个函数在内部调用自身本身,这个函数就是递归函数

递归函数特性:

(1)必须有一个明确的结束条件

(2)每次进入更深一层递归时,问题规模相比上次递归都应有所减少

(3)相邻两次重复之间有紧密的联系,前一次要为后一次做准备

(4)递归效率不高,递归层次过多会导致溢出

首先,我们可以从字面上来理解递归函数

递:传递出去的意思

归:回来的意思

递归函数就是一个有去有回的过程,以下一个简单的例子来解释递归函数:

实例:

计算一个10以下(包括10)整数的加法运算:

(1)初级写法:

n = 0

for i in range(11):

n += i

print(n)

(2)中级写法:

使用 reduce 高阶函数进行累计运算

from functools import reduce

print(reduce(lambda x, y: x+y, range(11)))

(3)递归函数的写法:

def add(n):

if n == 1:

return n

else:

return n + add(n -1)

print(add(10))

这三种方法,显然第二种是最简单的,但是这里是为了研究递归函数的用法,要了解递归函数的工作流程,就需要分解递归函数。

这里只是为了说明问题,调用 add(5) :

def add(n): # n = 5

if n == 1:

return n

else:

return n + add(n -1) # 5 + add(5 -1)

def add(n): # add(4)

if n == 1:

return n

else:

return n + add(n -1) # 4 + add(4 -1)

def add(n): # add(3)

if n == 1:

return n

else:

return n + add(n -1) # 3 + add(3 -1)

def add(n): # add(2)

if n == 1:

return n

else:

return n + add(n -1) # 2 + add(2 -1)

def add(n): # add(1)

if n == 1: # n = 1

return n # return 1

else:

return n + add(n -1)

以上是我们通过代码执行流程分解出来的过程信息。

每当函数内部调用自身的时候,外部函数挂起,执行内部函数,当内部函数执行完毕,然后在执行外部函数;

用简单的图形来表示,如下:

===> add(5)

===> 5 + add(4)

===> 5 + (4 + add(3))

===> 5 + (4 + (3 + add(2)))

===> 5 + (4 + (3 + (2 + add(1))))

===> 5 + (4 + (3 + (2 + 1)))

===> 5 + (4 + (3 + 3))

===> 5 + (4 + 6)

===> 5 + 10

===> 15

递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

实例:

使用递归函数实现一个三级菜单的效果

menu ={'北京': {'海淀': {'五道口': {'soho': {},'网易': {},'google': {}

},'中关村': {'爱奇艺': {},'汽车之家': {},'youku': {},

},'上地': {'百度': {},

},

},'昌平': {'沙河': {'北航': {},

},'天通苑': {},'回龙观': {},

},'朝阳': {},'东城': {},

},'上海': {'闵行': {"人民广场": {'炸鸡店': {}

}

},'闸北': {'火车战': {'携程': {}

}

},'浦东': {},

},'山东': {},

}

三级菜单

提示:在编写递归函数的时候要牢记以下三点:

(1)必须有一个明确的结束条件

(2)当数据按照一定规律执行的时候,才能考虑递归实现

(3)只有调用自身的函数才是递归函数

deftreeML(dic):whileTrue:for i indic:print(i)

key= input('>>>').strip()if key == 'q' or key == 'b':returnkeyelif key indic:

res=treeML(dic[key])if res == 'q':return 'q'treeML(menu)

递归函数实现三级菜单

二分查找算法与递归函数

二分查找算法:

简单来讲,就是一半一半的找。

二份查找实例:

有这样一个数列:

1,2,3,4,5

当我们想要查找数字:4

原始的办法:

从数列中一个一个遍历,直到找到 4 为止,查找了 4 次。

二分查找算法:

首先切一半得到:3,因为 3< 4 我们获取右半边的数列 4, 5

然后我们在切一半得到:4,4=4,在二分算法中,我们一共就找了 2 次就得到结果。

当我们想的多了,总结出更加便捷的方式,计算机才能更加高效的工作;

现在通过递归函数来实现,二分查找算法:

数列:

l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]

查找序列中是否有数字:83

l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]

基础实现:

def find(l, aim):

mid_index = len(l) // 2 # 这里需要取整数不能是小数

if l[mid_index] > aim: # 当取的值大于要找的值,取左边

find(l[:mid_index], aim) # 通过切片取list左边的值

elif l[mid_index] < aim: # 当取的值大于要找的值,取右边

find(l[mid_index+1:], aim) # 通过切片取list右边的值

else:

print(mid_index, l[mid_index]) # 数字比较只有三种情况,大于、小于、等于

find(l, 82)

上面的实例,虽然找到序列中含有 82 但是 索引位置是有问题的。修改如下:

l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]

def find(l, aim, start=None, end=None):

start = start if start else 0

end = len(l) -1 if end is None else end

mid_index = (end - start) // 2 + start

if start > end:

return None

if l[mid_index] > aim:

return find(l, aim, start, mid_index-1)

elif l[mid_index] < aim:

return find(l, aim, mid_index+1, end)

elif l[mid_index] == aim:

return mid_index, l[mid_index]

res = find(l, 82)

print(res)

# 执行结果:

# (22, 82)

以上递归函数,比较疑惑的地方:

end = len(l)-1 if end is None else end

这里为什么:len(l)-1

分析结果如下:

提示:如果要对递归函数进行分析,需要将代码执行流程分解开,查看就更加明显了。

l = [2,3,5]

def find(l, aim, start=None, end=None):

start = start if start else 0 # start = 0

end = len(l) if end is None else end # end = 3

mid_index = (end - start) // 2 + start # mid_index = (3-0) // 2 + 0 =1

if start > end:

return None

if l[mid_index] > aim:

return find(l, aim, start, mid_index-1)

elif l[mid_index] < aim: # 3 < 100

return find(l, aim, mid_index+1, end) # find(l, 6, 2, 3)

elif l[mid_index] == aim:

return mid_index, l[mid_index]

--------------------------------------------------------------------------------------------

通过第一步我们获取到:

find(l, 6, start=2, end=3)

l最大的索引为:2

--------------------------------------------------------------------------------------------

def find(l, aim, start=None, end=None): # find(l, 6, 2, 3)

start = start if start else 0 # start = 2

end = len(l) if end is None else end # end = 3

mid_index = (end - start) // 2 + start # mid_index = (3-2) // 2 + 2 =2

if start > end:

return None

if l[mid_index] > aim:

return find(l, aim, start, mid_index-1)

elif l[mid_index] < aim: # 5 < 6

return find(l, aim, mid_index+1, end) # find(l, 6, 3, 3)

elif l[mid_index] == aim:

return mid_index, l[mid_index]

--------------------------------------------------------------------------------------------

通过第二步我们获取到:

find(l, 6, start=3, end=3)

l最大的索引为:2

--------------------------------------------------------------------------------------------

def find(l, aim, start=None, end=None): # find(l, 6, 3, 3)

start = start if start else 0 # start = 3

end = len(l)-1 if end is None else end # end = 3

mid_index = (end - start) // 2 + start # mid_index = (3-3) // 2 + 3 = 3

if start > end:

return None

if l[mid_index] > aim: # l 最大的索引为:2 这里:l[3] 报错啦,因此 end = len(l)-1 if end is None else end

return find(l, aim, start, mid_index-1)

elif l[mid_index] < aim:

return find(l, aim, mid_index+1, end) # find(l, 6, 3, 3)

elif l[mid_index] == aim:

return mid_index, l[mid_index]

附加题:

使用递归函数求斐波拉契数列.

首先斐波拉契数列如下:

1,1,2,3,5,8

规律:从第三位开始,后面的值是前面两个值的和

def fib(n):

if n == 1 or n == 2:

return 1

return fib(n -1) + fib(n -2)

上面的函数是按照斐波拉契数列规律写出来的,思路是没问题的,但是在函数内部调用两次自身函数,这样的效率非常慢。

因此在使用递归函数时,一定要注意在函数内部只能调用一个,否则严重影响执行效率

上面的递归函数修改如下:

count = 0

def fib(n, a=0, b=1):

# 每次递归获取全局变量count = 0

global count

# 在递归函数中,count = 1

count += 1

# 当 1 < n -1 时,进行函数的递归计算

if count < n-1:

return fib(n, b, a+b)

# 当 1 >= n -1 时,n = 2 或者 n =1 返回 a + b = 0 + 1 = 1

elif count >= n -1:

return a+b

f = fib(10)

print(f)

python编写递归函数_[ python ] 递归函数相关推荐

  1. python编写代码_用 Python 编写干净、可测试、高质量的代码

    用 Python 编写干净.可测试.高质量的代码 Noah Gift 2010 年 12 月 20 日发布 简介 编写软件是人所承担的最复杂的任务之一.AWK 编程语言和 "K and R ...

  2. python编写函数_如何用Python编写自己喜欢的R函数

    python编写函数 数据科学和机器学习的伟大现代斗争之一是" Python vs. R". 毫无疑问,近年来两者都已经取得了巨大的发展,成为数据科学,预测分析和机器学习的顶级编程 ...

  3. python编写登录_通过Python编写一个简单登录功能过程解析

    通过Python编写一个简单登录功能过程解析 需求: 写一个登录的程序, 1.最多登陆失败3次 2.登录成功,提示欢迎xx登录,今天的日期是xxx,程序结束 3.要检验输入是否为空,账号和密码不能为空 ...

  4. 如何用python编写程序_如何进行Python程序的编写

    一.使用Python自身提供的交互式解释器 在Linux.Windows.Mac OS的命令行窗口或Shell窗口,执行python命令,启动Python交互式解释器.交互式解释器会等待用户输入Pyt ...

  5. effective python编写高质量Python代码的59个有效方法 pdf下载

    用Python编写程序,是相当容易的,所以这门语言非常流行.但若想掌握Python所特有的优势.魅力和表达能力,则相当困难,而且语言中还有很多隐藏的陷阱,容易令开发者犯错.本书使用了59个主题讲述了p ...

  6. python 数学期望_(Python)零起步数学+神经网络入门

    摘要: 手把手教你用(Python)零起步数学+神经网络入门! 在这篇文章中,我们将在Python中从头开始了解用于构建具有各种层神经网络(完全连接,卷积等)的小型库中的机器学习和代码.最终,我们将能 ...

  7. python 病毒 基因_#Python#提取基因对应的蛋白质名

    提取基因对应的蛋白质官方名 最开始,是需要将基因跟其编码的蛋白质对应起来,找遍了各种数据库都没发现有相关的注释文件,Uniprot作为处理蛋白质的大佬,结果里都有,肯定有办法能够满足需求. 搜索TP5 ...

  8. python keyboard模块_[python] PyMouse、PyKeyboard用python操作鼠标和键盘

    1.PyUserInput 简介 PyUserInput是一个使用python的跨平台的操作鼠标和键盘的模块,非常方便使用.支持的平台及依赖如下: Linux - Xlib Mac - Quartz, ...

  9. python编写函数_浅谈Python 函数式编程

    匿名函数lambda表达式 什么是匿名函数? 匿名函数,顾名思义就是没有名字的函数,在程序中不用使用 def 进行定义,可以直接使用 lambda 关键字编写简单的代码逻辑.lambda 本质上是一个 ...

最新文章

  1. 如何使用eclipse打开已有工程
  2. T型加速算法fpga实现思想研究
  3. 【北航】Bella 姐姐发辣条(贪心)
  4. 会涨价么?苹果iPad和MacBook拟采用三星OLED屏幕
  5. lofter 爬虫_Lofter德赫标签日榜 | 200703
  6. mybatis 同名方法_判断同名股票是否存在的MyBatis查询函数写法
  7. C++多线程map读写加锁
  8. flex mx:TabNavigator进行选项卡切换,需要进行交互时。发生Error #1009错误
  9. 票据纸张尺寸对照表_粉丝要求,这期整理一版平面设计必备各种尺寸知识(收藏版))...
  10. 大数据开发之CDH篇----cloudera-scm-agent启动不了后的一堆事
  11. 券商理财和银行理财的不同
  12. JavaScript (一) js的介绍及基本语法变量
  13. 工作中可能用到的——集中式版本控制系统SVN
  14. 【转】LVTTL与LVCMOS区别
  15. 生命游戏(Java)
  16. 低版本IntelliJ IDEA升级到IntelliJ IDEA 2021.3.3
  17. 双线机房双网卡双ip DNSpod智能DNS解析和路由设置
  18. 装系统中----专业名词小结
  19. 郑州天梵是否为正统古法易筋洗髓经传承者能否达到养生的目的呢?
  20. 馈线接头制作步骤及说明

热门文章

  1. 科研素养:了解学术会议的形式和结构
  2. 计算机英语2008影印版,(计算机英语2008影印版课后单词翻译.doc
  3. 数字电路逻辑设计笔记(2):逻辑代数基础
  4. 系统提示“该设备无法启动(代码:10)”,USB设备不能开始工作怎么办?
  5. 【第105期】Python将提速2-5倍!你期待吗
  6. 回忆杀,pythonQ版泡泡堂
  7. Type3 PDF文档处理
  8. easyExcel导入失败提示用户第几行有误并回滚数据
  9. 蓝桥杯刷题021——填字母游戏(DFS)
  10. 百度知道引流规则,这个方法对于精准营销很有效果