迭代是人,递归是神。 —— L.Peter Deutsch
定义:函数在执行的过程中调用自己。
递归算法一般用于解决三类问题:
1 数据的另一是按照递归定义的。比如斐波那契函数
2 问题解法按照递归算法实现。比如回溯。
3 数据的数据类型是按照递归定义的。比如树的遍历,图的搜索。
递归的应用
三级菜单
实现一级一级打印,按 b 返回上一级,按 q 直接退出。
menu = { '北京': { '海淀': { '五道口': { 'soho': {}, '网易': {}, 'google': {} }, '中关村': { '爱奇艺': {}, '汽车之家': {}, 'youku': {}, }, '上地': { '百度': {}, }, }, '昌平': { '沙河': { '老男孩': {}, '北航': {}, }, '天通苑': {}, '回龙观': {}, }, '朝阳': {}, '东城': {}, }, '上海': { '闵行': { "人民广场": { '炸鸡店': {} } }, '闸北': { '火车战': { '携程': {} } }, '浦东': {}, }, '山东': {}, }
# n=0 def foo(dic): while True: for key in dic: print(key) cmd=input('==>') if cmd=='b': break elif cmd=='q': return 'q' elif cmd in dic: res=foo(dic[cmd]) # global n # n+=1 # print('第{}次:'.format(n),res) if res=='q': #res 是取下一级的返回值,只有cmd=='q',才有返回值‘q’。注释掉的代码试了一下,break退出一层循环是res是None。
return 'q' #这两行代码我觉的是精髓。 return 本身也有终止函数执行的效果。
foo(menu)
例子二:
有⼀个数据结构如下所示,请编写⼀个函数从该结构数据中返回由指定的字段和对应的值组成的字
典。如果指定字段不存在,则跳过该字段。(10分)
data:{"time":"2016-08-05T13:13:05",
"some_id":"ID1234",
"grp1":{ "fld1":1,
"fld2":2},
"xxx2":{ "fld3":0,
"fld5":0.4},
"fld6":11,
"fld7":7,
"fld46":8}
fields:由"|"连接的以"fld"开头的字符串,如:fld2|fld3|fld7|fld19
def select(data,fields):
# TODO:implementation
return result
典。如果指定字段不存在,则跳过该字段。(10分)
data:{"time":"2016-08-05T13:13:05",
"some_id":"ID1234",
"grp1":{ "fld1":1,
"fld2":2},
"xxx2":{ "fld3":0,
"fld5":0.4},
"fld6":11,
"fld7":7,
"fld46":8}
fields:由"|"连接的以"fld"开头的字符串,如:fld2|fld3|fld7|fld19
def select(data,fields):
# TODO:implementation
return result
data={"time":"2016-08-05T13:13:05", "some_id":"ID1234", "grp1":{ "fld1":1, "fld2":2}, "xxx2":{ "fld3":0, "fld5":0.4}, "fld6":11, "fld7":7, "fld46":8} l='fld2|fld3|fld7|fld19'.split('|') def foo(dic,lst): result = {} for i in dic : if i in lst: result[i]=dic[i] if type(dic[i])==dict: res=foo(dic[i],lst) result.update(res) return result res=foo(data,l) print(res)
总结:递归套递归本身简单,但是涉及到返回值就有点拿不准了。其中,单独一层函数执行本身就有返回值。上面两个例子都是拿到下一层的返回值。注意: 两个例子都有 res=foo( ),代表拿到下一层函数的返回值!
第二个例子result还可以是全局变量。这样写的话,难度就大大降低了。但是离递归的感觉就有点远了。
在第二个例子现成的基础上,不管有多少层,最终都是要返回一个result字典,字典是可变类型,so,定义函数的时候,可以将result设定为默认参数。Nice 思路。这是这个题的更加好的做法。根本的思路还是总结的第一点。
l='fld2|fld3|fld7|fld19'.split('|') def foo(dic,lst,result={}): for i in dic : if i in lst: result[i]=dic[i] if type(dic[i])==dict: foo(dic[i],lst) return result res=foo(data,l) print(res)