本章包含大量伪代码,伪代码是对手头问题的简要描述,看着像代码,但更接近自然语言。介于自然语言和编程语言之间,是一种描述算法的语言。
1. 递归
* 盒子里面有盒子,而盒子里的盒子又有盒子,钥匙在某个盒子中,有什么方法能找到钥匙?
方法一:
1> 创建一个要查找的盒子堆
2> 从盒子堆中取出一个盒子,在里面找
3> 如果找到的是盒子,就将其加入盒子堆中,以便以后再查找
4> 如果找到钥匙,则大功告成
伪代码:
def look_for_key(main_box): pile = main_box.make_a_pile_to_look_through() while pile is not empty: box = pile.grab_a_box() for item in box: if item.is_a_box(): pile.append(item) elif item.is_a_key(): print("found the key")
示例代码:
def lookkey(main_box): for box in main_box: for pile in box: if pile == "box": main_box.append(pile) print("It's a box") elif pile == "key": print("found the key") A = [["box"],["box"],["key"],["box"]] lookkey(A)
运行:
1. It's a box 2. It's a box 3. found the key 4. It's a box
方法二:
1> 详细检查盒子中的每样东西
2> 如果是盒子,就返回第一步
3> 如果是钥匙,就大功告成
伪代码:
def look_for_key(box): for item in box: if item.is_a_box(): look_for_key(item) elif item.is_a_key(): print("found the key")
示例代码:
def LookKey(Box): for item in Box: if type(item) == list: print("There's another box in here.") LookKey(item) elif type(item) == str: if item == "box": print("There is not key in the box") print() elif item == "key": print("found the key") print() B = [["box"],"box",["key"],["box"]] LookKey(B)
运行:
There's another box in here. There is not key in the box There is not key in the box There's another box in here. found the key There's another box in here. There is not key in the box
2. 基线条件和递归条件
编写递归函数时,必须告诉它何时停止递归
每个递归函数都有两部分:基线条件和递归条件
递归条件指的是函数自己调用自己,而基线条件则指的是函数不再调用自己,从而避免形成无限循环
* 倒计时函数:3……2……1
def countdown(i): print(i) countdown(i-1)
运行结果:3……2……1……0……-1……-2……
无限循环
添加基线条件:
def countdown(i): print(i) if i <= 0: # 基线条件 return else: # 递归条件 countdown(i-1)
运行结果:3……2……1……0
3. 栈
处理待办事项清单,一叠便条要简单得多,插入的待办事项放在清单的最前面,读取待办事项时,你只读取最上面的那个,并将其删除。因此只有两种操作:压入(插入)和弹出(删除并读取)
栈是一种简单的数据结构
①调用栈
计算机在内部使用被称为调用栈的栈
下面是一个简单函数,作用是问候用户
def greet2(name): print("how are you," + name + "?") def bye(): print("ok bye!") def greet(name): print("hello," + name + "!") greet2(name) print("getting ready to say bye……") bye() greet("lilrain")
运行:
1. hello,lilrain! 2. how are you,lilrain? 3. getting ready to say bye…… 4. ok bye!
② 递归调用栈
计算阶乘的递归函数
def fact(x): if x == 1: return 1 else: return x * fact(x - 1) print(fact(3))
运行:
6
详解分析调用fact(3)时调用栈是如何变化的:
(栈顶的方框指出了当前执行到了什么地方)
每个fact调用都有自己的x变量,在一个函数调用中不能访问另一个的x变量
回归盒子堆的递归解决方法(二):
盒子堆存储在了栈中,这个栈包含未完成的函数调用,每个函数调用都包含还未检查完的盒子,无需自己跟踪盒子堆——栈替你这样做了
使用栈虽然方便,但也要付出代价:储存详尽的信息可能占用大量的内存。每个函数调用都要调用一定的内存,如果栈很高,就意味着计算机存储了大量函数调用的信息。这种情况下,有两种选择:1>重新编写代码; 2>使用尾递归
4. 小结
①递归指的是调用自己的函数
②每个递归函数都有两个条件:基线条件和递归条件
③栈有两种操作:压入和弹出
④所有函数调用都进入调用栈
⑤调用栈可能很大,这将占用大量内存