这是我从一本书中解释递归的代码.问题是我不明白程序采取的步骤:
var hanoi = function(disc,src,aux,dst) { if (disc > 0) { hanoi(disc - 1,dst,aux); document.write("Move disc " + disc + " from " + src + " to " + dst + "<br />"); hanoi(disc - 1,dst); } }; hanoi(3,"src","aux","dst");
输出如下:
Move disc 1 from src to dst Move disc 2 from src to aux Move disc 1 from dst to aux Move disc 3 from src to dst Move disc 1 from aux to src Move disc 2 from aux to dst Move disc 1 from src to dst
有人可以一步一步地破坏这一点吗?这对我来说是非常有帮助的.
解决方法
河内塔楼最简单的解决方案可能是这样的:
将x盘从钉A移动到钉C,使用钉B作为“辅助”栓:
>将x-1光盘从钉A移动到钉B,使用钉C作为辅助钉.
>将第x个光盘从钉A移动到钉C(不需要辅助,因为您只能移动一张光盘).
>使用钉A作为辅助钉,将x-1碟从钉板B移动到钉C上.
请注意,为了移动x光盘,您必须移动x-1张光盘.您可以使用相同的功能来移动这些x-1光盘,并且只需切换哪个连接头就是源,目标和辅助连接.这就是河内的塔楼这样一个常见的递归的例子,这就是你需要在问题中看到的模式,以便为你的递归工作.它不需要“移动x-1光盘”,当然可以这样的“列出这个子文件夹”.树(就像具有子文件夹等的目录)是递归闪耀的另一个地方.与其他作业一样,为了在一个项目上完成这项工作,您可能需要对子项目做同样的工作.
现在,为了有用的递归,你需要一个“基本情况” – 递归将停止的条件.如果不这样做,代码将永远运行(或至少直到内存不足或溢出调用堆栈).这种情况发生在x == 0(因为移动0光盘意味着你什么都不做,因为在功能的周围).它也可能是当x == 1,因为你不必递归,但额外的,如果在每个河内调用之前会增加一点噪音(并且递归解决方案的主要好处是它的简单性).无论如何,当x == 0时,函数返回而不做任何事情.调用它的函数(它有x == 1)现在可以继续执行其操作 – 在这种情况下,说“将光盘1从src移动到dest”,然后再次使用args切换来调用hanoi函数.
流程有点像这样:
hanoi(3,dest) hanoi(2,dest,aux) hanoi(1,dest) hanoi(0,aux) // no op print "Move 1 from src to dest" hanoi(0,dest) // no op print "Move 2 from src to aux" hanoi(1,aux) hanoi(0,src) // no op print "move 1 from dest to aux" hanoi(0,aux) // no op print "move 3 from src to dest" hanoi(2,dest) hanoi(1,src) hanoi(0,dest) // no op print "Move 1 from aux to src" hanoi(0,src) // no op print "Move 2 from aux to dest" hanoi(1,aux) // no op print "move 1 from src to dest" hanoi(0,dest) // no op