汉诺塔问题的两种解法(4)

第四节 汉诺塔问题的递归解法——移动所有盘子

上一节我们实现了连续移动两个盘子(数字),现在我们发挥一点儿想象力,将上一节的两个盘子当作一个盘子来处理,从而得出移动3个盘子的过程,代码如图22所示。

图22 连续移动三个盘子(数字)的过程

我们还可以写出连续移动4个盘子的过程,代码如图23的左图所示。在暂停按钮的点击事件中调用该过程,即可执行移动操作。读者不妨测试一下,看看虚实。

图23 连续移动4个盘子的过程

以此类推,我们可以编写出连续移动任意多个盘子的过程,如果盘子数为N,那么连续移动N个盘子的过程,要依赖于移动前N-1个盘子的过程。像这样,对N个对象的操作要依赖于对前N-1个对象的操作,解决这样的问题,需要用到一种叫做“递归”的编程方法,即,在一个过程内部调用这个过程本身。下面我们编写移动N个盘子的过程——移动N,代码如图24所示。

图24 连续移动N个盘子的过程

上述过程里增加了一个参数N,这是至关重要的一步,它的作用有两点:一是借助于N,我们得以描述数量相邻的两组盘子之间的移动规律,也就是在N与N-1之间建立联系,如图24中条件语句中的“否则”分支部分;二是为递归调用提供了一个出口,即当N=0时,退出递归,执行条件语句的“则”分支。为递归程序设置出口,这是使用递归方法的第一要务,否则,程序有可能进入死循环。

在暂停按钮的点击事件中调用移动N过程,参数N为左列表的长度,代码如图25所示。

图25 连续移动N个数字

在测试手机上的输入框中输入数字10,然后点击开始按钮,之后再点击暂停按钮,程序的运行结果如图26所示。

图26 测试:连续移动10个数字

这次测试在我的手机上运行了很长时间,我很好奇究竟用了几秒钟,5秒?10秒?还是用程序来测一下吧,代码如图27所示,测试结果如图28所示,竟然耗时24秒!

图27 测量运算时长

图28 运算时长的测试结果——24秒钟

前面提到过移动次数与盘子数n之间的关系,移动次数 =

,当n=10时,次数=1023。如果仅仅是1023次四则运算,用时不会超过1秒钟,但是当涉及到列表的操作时(添加、删除列表项),运算量呈几何级数增长,况且递归调用过程中,消耗大量内存来保存局部变量——过程的参数,由此导致的资源及运算力的消耗都是巨大的。

程序写到这里,已经实现了解决汉诺塔问题的目标,不过,心中总有些不甘,希望能够将数字移动的过程呈现出来,于是有了后面的几节。

== 未完待续 ==

(0)

相关推荐

  • 你会玩汉诺塔吗?——让递归算法来帮你,只需“3步”

    今天我们来介绍一种很常见的算法--递归. 递归函数 什么是递归?简单的说,递归就是通过不断调用自己,来完成不断循环的一个过程. 可能概念有些拗口,我们编写一个递归函数来说明.斐波那契数列大家都知道,它 ...

  • 关于C++的递归(以汉诺塔为例)

    关于C++,hanoi塔的递归问题一直是个经典问题,我们学习数据结构的时候也会时常用到, 因为它的时间复杂度和空间复杂度都很高,我们在实际的应用中不推荐使用这种算法,移动n个盘子, 需要2的n次幂减一 ...

  • 汉诺塔:闪烁在数学和心理学交汇之地奇妙问题

    "当 64 金片移动完成时宇宙会在一瞬间闪电式毁灭. " 翻译小组成员介绍: 向海飞 武汉市人,2002年华中理工大学应用电子技术专业本科毕业.现在洛阳工作. 文章: plus.m ...

  • Py:递归求解汉诺塔,简单的几行编程可以搞定很高层的三柱汉诺塔游戏

    Py:递归求解汉诺塔,简单的几行编程可以搞定很高层的三柱汉诺塔游戏 输出结果 核心代码 def hanoi(n,x,y,z): if n==1: print(x,'--→',z) else: hano ...

  • 汉诺塔算法

    汉诺塔算法 ----C++语言递归实现 线上幽灵 2018-04-24 17:19:59 8159 收藏 26分类专栏:算法 文章标签:汉诺塔版权声明:本文为博主原创文章,遵循 CC 4.0 BY-S ...

  • 汉诺塔问题,五个盘子具体走法

    我移了三盘的和四盘的,就是推不出五盘的...笨嘛...等指教 1个回答 满意答案 fatso1118 推荐于 2017.12.15 五个柱子!分别为1号 2号 3号 五个盘子 A B C D E 这样 ...

  • 汉诺塔问题的两种解法(1)

    汉诺塔是一种益智玩具,源自古老的印度.如图1.图2及图3所示,有三根柱子,若干个大小不等的圆盘按顺序依次叠落在起点(左侧)的柱子上,通过多次移动后,全部圆盘要叠落在终点(右侧)的柱子上.移动必需遵守两 ...

  • 汉诺塔问题的两种解法(2)

    第二节 关键性结论 通过反复实践与观察,我们发现了解决汉诺塔问题的思路.无论圆盘的数量有多少,我们都可以把它们当作2个盘子来处理.假设共有N个圆盘,我们把它们想象为两个圆盘,其中一个圆盘是整个塔的塔底 ...

  • 汉诺塔问题的两种解法(3)

    第三节 汉诺塔的递归解法--移动两个盘子 一.用户界面 在App Inventor中创建一个项目,命名为汉诺塔,用户界面在手机中的样子如图11所示,在AppInventor设计视图中,为项目添加组件, ...

  • 汉诺塔问题的两种解法(5)

    第五节 条件限定法--限定条件 限定条件法不关注移动过程的整体规律,而着眼于具体的移动路径(规定每一步移动的出发点及落脚点),对每一种可能的移动路径设置限定条件,通过对限制条件的设置及调整,逐渐找到最 ...

  • 汉诺塔问题的两种解法(6)

    第六节 条件限定法--变量与过程 在开始编写程序之前,首先将此前已经完成的项目另存为"汉诺塔2",并在汉诺塔2的基础上,编写新的程序.原有项目中需要保留的全局变量及过程如图30所示 ...

  • 汉诺塔问题的两种解法(7)

    第七节 条件限定法--演示移动过程 上一节完善了2个已有过程,并新增了6个有返回值的过程,完成了对出发点.落脚点的选择,有了这些结果,本节可以收获成果了. 一.两个无返回值过程 (1)不连续移动 出发 ...

  • 汉诺塔问题的两种解法(8)

    第八节 求解过程小结 我们已经完成了对数字(盘子)的移动,并成功地演示了数字的移动过程.阅读并理解前面几节中的程序并不难,就这个例子而言,难的不是程序,而是编写程序之前对移动规律的归纳与整理,这也正是 ...

  • 科目余额表,只取最明细一级数据?Power Query和Power Pivot两种解法!

    小勤:下面这个表里是从财务系统里导出来的科目表,怎么能只保留本币里的最底层明细数据?最终本币列结果如右侧所示: 大海:能通过判断下一行中的科目编码是否包含本行科目编码来判断当前行是否为非明细行吗? 小 ...

  • 分享一道圆,两种解法,一种倍长中线余弦定...

    分享一道圆,两种解法,一种倍长中线余弦定...