递归

递归

假设你在祖母的阁楼中发现一个上锁的神秘手提箱。

祖母告诉你,钥匙可能在下面这个盒子中。

这个盒子里有盒子,而盒子里的盒子又有盒子。钥匙就在某个盒子中。
为找到钥匙,你将使用什么算法?先想想这个问题,再接着往下看。

第一种方法使用的是while循环:只要
盒子堆不空,就从中取一个盒子,并在其中仔细查找。

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 look_for_key(box):
	for item in box:
		if item.is_a_box():

这两种方法的作用相同,但在我看来,第二种方法更清晰。递归只是让
解决方案更清晰,并没有性能上的优势。实际上,在有些情况下,使用
循环的性能更好。我很喜欢Leigh Caldwell在Stack Overflow上说的一句
话:“如果使用循环,程序的性能可能更高;如果使用递归,程序可能
更容易理解。如何选择要看什么对你来说更重要。

基线条件和递归条件

由于递归函数调用自己,因此编写这样的函数时很容易出错,进而导致
无限循环。例如,假设你要编写一个像下面这样倒计时的函数。

> 3 ... 2 ... 1

为此,你可以用递归的方式编写,如下所示:

def countdown(i):
	print i
	countdown(i-1)

如果你运行上述代码,将发现一个问题:这个函数运行起来没完没了!

3...2...1...0...-1...-2...等等

编写递归函数时,必须告诉它何时停止递归。正因为如此,每个递归函
数都有两部分:基线条件(base case)和递归条件(recursive case)。
递归条件指的是函数调用自己,而基线条件则指的是函数不再调用自
己,从而避免形成无限循环。
我们来给函数countdown添加基线条件。

def countdown(i):
	print i
	if i <= 1: ←------基线条件
		return
	else: ←------递归条件
	countdown(i-1)

现在,这个函数将像预期的那样运行,如下所示。

原文地址:https://www.cnblogs.com/zzsy/p/12684807.html