我在学校里很难理解递归。每当教授谈到它的时候,我似乎都懂了,但当我自己尝试的时候,它完全震撼了我的大脑。
我整晚都在尝试着解决《Towers of Hanoi》这款游戏,结果完全出乎我的意料。我的课本只有大约30页关于递归的内容,所以它不是很有用。有人知道哪些书籍或资源可以帮助澄清这个话题吗?
我在学校里很难理解递归。每当教授谈到它的时候,我似乎都懂了,但当我自己尝试的时候,它完全震撼了我的大脑。
我整晚都在尝试着解决《Towers of Hanoi》这款游戏,结果完全出乎我的意料。我的课本只有大约30页关于递归的内容,所以它不是很有用。有人知道哪些书籍或资源可以帮助澄清这个话题吗?
当前回答
这与其说是一个问题,不如说是一个抱怨。关于递归你有更具体的问题吗?就像乘法一样,人们不会写很多关于它的东西。
说到乘法,想想这个。
问题:
* b是什么?
答:
如果b = 1,就是a。 否则就是a+a*(b-1)
* (b - 1)是什么?请参考上面的问题来解决这个问题。
其他回答
想想工蜂。它试着酿蜂蜜。它完成了自己的工作,并期待其他工蜂来酿造剩下的蜂蜜。蜂房满了,蜂房就停了。
把它想象成魔法。你有一个与你要实现的函数同名的函数,当你给它子问题时,它就会帮你解决它,你唯一需要做的就是把你的部分的解与它给你的解集成起来。
例如,我们想计算一个列表的长度。让我们用magical_length来调用我们的函数,用magical_length来调用神奇的助手 我们知道,如果我们给出没有第一个元素的子列表,它会神奇地给我们子列表的长度。那么我们唯一需要考虑的就是如何将这些信息与我们的工作结合起来。第一个元素的长度是1,而magic_counter给出了子列表的长度n-1,因此总长度是(n-1) + 1 -> n
int magical_length( list )
sublist = rest_of_the_list( list )
sublist_length = magical_length( sublist ) // you can think this function as magical and given to you
return 1 + sublist_length
然而,这个答案是不完整的,因为我们没有考虑如果我们给出一个空列表会发生什么。我们认为我们的列表总是至少有一个元素。因此,我们需要思考,如果给我们一个空列表,答案显然是0,那么答案应该是什么。所以把这些信息加到我们的函数中,这被称为基础/边缘条件。
int magical_length( list )
if ( list is empty) then
return 0
else
sublist_length = magical_length( sublist ) // you can think this function as magical and given to you
return 1 + sublist_length
如果你想要一本很好地用简单的术语解释递归的书,可以看看Gödel,埃舍尔·巴赫:道格拉斯·霍夫施塔特的《永恒的金辫子》,特别是第五章。除了递归,它还能很好地以一种可理解的方式解释计算机科学和数学中的许多复杂概念,一个解释建立在另一个解释的基础上。如果你以前没有接触过这类概念,这可能是一本非常令人兴奋的书。
我会用一个例子来解释。
你知道n!意味着什么?如果不是:http://en.wikipedia.org/wiki/Factorial
3! Is 1 times 2 times 3, which is 6
下面是一些伪代码
function factorial(n) {
if (n==0) return 1
else return (n * factorial(n-1))
}
让我们试试吧:
factorial(3)
n是0吗?
no!
所以我们在递归中深入挖掘:
3 * factorial(3-1)
3 minus 1 is 2
2 == 0?
no!
所以我们要深入! 3 * 2 *阶乘(2-1) 2-1 = 1
1 == 0吗?
no!
所以我们要深入! 3 * 2 * 1 *阶乘(1-1) 1-1 = 0
0 == 0?
yes!
我们有一个小问题
所以我们有 3 * 2 * 1 * 1 = 6
我希望这对你有所帮助
Common Lisp中的简单递归示例:
MYMAP对列表中的每个元素应用一个函数。
1)空列表没有元素,所以我们返回空列表-()和NIL都是空列表。
2)将函数应用到第一个列表,对列表的其余部分调用MYMAP(递归调用),并将两个结果合并到一个新列表中。
(DEFUN MYMAP (FUNCTION LIST)
(IF (NULL LIST)
()
(CONS (FUNCALL FUNCTION (FIRST LIST))
(MYMAP FUNCTION (REST LIST)))))
让我们观察跟踪执行。在输入函数时,输出参数。在退出函数时,输出结果。对于每个递归调用,输出将按级别缩进。
这个例子对列表(1 2 3 4)中的每个数字调用SIN函数。
Command: (mymap 'sin '(1 2 3 4))
1 Enter MYMAP SIN (1 2 3 4)
| 2 Enter MYMAP SIN (2 3 4)
| 3 Enter MYMAP SIN (3 4)
| | 4 Enter MYMAP SIN (4)
| | 5 Enter MYMAP SIN NIL
| | 5 Exit MYMAP NIL
| | 4 Exit MYMAP (-0.75680256)
| 3 Exit MYMAP (0.14112002 -0.75680256)
| 2 Exit MYMAP (0.9092975 0.14112002 -0.75680256)
1 Exit MYMAP (0.841471 0.9092975 0.14112002 -0.75680256)
这是我们的结果:
(0.841471 0.9092975 0.14112002 -0.75680256)
实际上,使用递归是为了降低手头问题的复杂性。你应用递归,直到你达到一个简单的基本情况,可以很容易地解决。这样就可以解决最后一个递归步骤。用这些递归步骤就可以解决最初的问题。