代码小工蚁的#《算法图解》#学习笔记-C3递归
C3 递归recursion
一、调用栈
执行栈(execution stack),又称控制栈(control stack)、运行时栈(run-time stack)和调用栈(call stack)。
栈(stack)是限定仅在表尾进行压入(插入)和弹出(删除并读取)操作的线性表。
表尾端称为栈顶(top),相应地,表头端称为栈底(bottom)。[1]
栈遵循LIFO后进先出(Last In First Out)原则。
压入(插入)push (insert)
弹出(删除并读取)pop (remove and read)
调用栈保持程序调用的返回地址,以及本地变量、参数传递、环境传递等数据。
无限递归(Infinite recursion)或过多的堆栈层级(占用大量的内存)会导致堆栈溢出(stack overflow)
一般而言,高级语言会将调用栈的细节隐藏至后台。
扩展:
世界上最大的开发者社区StackOverflow:
https://stackoverflow.com/
二、递归
从一个故事开始的递归:
从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?
从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?
从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?
……
在计算机中,递归是指一种通过重复将问题分解为同类的子问题的方法。
换一种表述就是函数自己调用自己。
每个递归函数都有两个条件:基线条件base case和递归条件recursive case。
基线条件:函数不再调用自己,避免无限循环。
递归条件:函数调用自己。
好处:递归使函数的定义和算法的描述比使用非递归方法更简明。
递归的强大之处在于它允许用户用有限的语句描述无限的对象。
因此,在计算机科学中,递归可以被用来描述无限步的运算,尽管描述运算的程序是有限的。
——Nicklaus Wirth(对,就是提出“算法+数据结构=程序”的尼古拉斯·沃斯)[3]
缺点:递归调用可能占用大量的内存。
处理:重写代码改用循环;使用尾递归tail recursion。
递归应用:求阶乘5!
5!= 5 * 4 * 3 * 2 * 1
代码片断:
def fact(x):
if x == 1:
return 1
else:
return x*fact(x-1)
print('5! = ', fact(5))
注意代码中的基线条件与递归条件。
python中已有 math.factorial()
方法可直接求阶乘。
扩展:递归典型问题:梵塔问题(汉诺塔问题)
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。
该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘。
游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。
操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。[4]
C语言源码参考[5]
代码片断:
# coding=utf-8
# 汉诺塔问题演示
def hanoi(n, p1, p2, p3):
# 移动步数steps,全局变量
global steps
steps += 1
if n == 1:
print('Move sheet {} from {} to {}.'.format(n, p1, p3))
print('-' * 30)
else:
hanoi(n-1, p1, p3, p2)
print('Move sheet {} from {} to {}'.format(n, p1, p3))
hanoi(n-1, p2, p1, p3)
return steps
if __name__ == '__main__':
n = int(input('请输入盘数1-8:'))
# 移动步数统计steps
steps = 0
steps_num = hanoi(n,'A', 'B', 'C')
print(steps_num)
按要求将64个盘从A柱移动到C柱,按1秒移一下,完成任务需要5800多亿年!!!
(2**64 - 1)/3600/24/365
小伙伴们输入数字时就不要输入64了,不信你试试。
[1]百度百科:执行栈
https://baike.baidu.com/item/%E6%89%A7%E8%A1%8C%E6%A0%88/22105693?fr=aladdin
[2]图片来自:知乎@ninechapter 若侵删
https://www.zhihu.com/question/20507130
[3]维基百科
https://zh.wikipedia.org/wiki/%E9%80%92%E5%BD%92_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)
[4]百度百科:汉诺塔问题
https://baike.baidu.com/item/%E6%B1%89%E8%AF%BA%E5%A1%94%E9%97%AE%E9%A2%98/1945186?fr=aladdin
[5]汉诺塔Tower of Hanoi
http://www.it165.net/pro/html/201508/51045.html