递归--汉诺塔

汉诺塔

汉诺塔作为一个数学游戏,经常出现在计算机基础教学中,用于说明递归的作用。游戏需要三根石柱和一组中间带孔的圆盘,将所有圆盘从最左侧第一根石柱移动到最右侧的第三根石柱。
圆盘最初摞在最左侧的石柱上,顺序是下面的圆盘大于上面的圆盘。移动时必须遵循以下规则:

  • 一次只能移动一个圆盘
  • 一个圆盘不能放在另一个比它小的圆盘上
  • 所有圆盘都必须摞在石柱上,除非在移动中
    先举几个例子,看看圆盘数量不同的时候,游戏有什么解法。
    1.如果只有一个圆盘,移动方法很简单:将圆盘从石柱1移动到石柱3.
    2.如果有两个圆盘,则需要移动三次:
    • 将圆盘1移动到石柱2.
    • 将圆盘2移动到石柱3
    • 将圆盘1移动到石柱3
      (注意这个玩法中,石柱2用于临时堆放圆盘。)
      以下的概述描述了游戏玩法模拟的递归算法。请注意,在这个算法中。使用变量A、B、C来保存石柱编码。
      要将n个圆盘从石柱A移动到石柱C上,用石柱B作为临时存放处,需要一下步骤:
      如果n>0,则:
  • n-1个圆盘从石柱A移动到石柱B,石柱C作为临时存放处
  • 把剩余的圆盘从石柱A移动到石柱C
  • n-1个圆盘从石柱B移动到石柱C,石柱A作为临时存放处
  • 结束
    当没有更多的圆盘需要移动时,便是算法的基础部分。
    下面的伪代码是一个模块,用于实现该算法。请注意,该模块并没有实际移动任何圆盘,而是显示指令,指明所有要执行的移动:
/*
num —     移动的圆盘数
fromPeg — 圆盘将要离开的石柱
toPeg —   圆盘将要移动到的石柱
tempPeg — 用于临时存放处的石柱
*/
Module moveDiscs(Integer num,Integer fromPeg,Integer toPeg,Integer tempPeg)
    if num > 0 Then
         //下递归调用语句是一个指令,除一个圆盘之外,将所有圆盘从fromPeg 移动到 tempPeg,将toPeg作为临时存放处
          moveDiscs(Integer num-1,Integer fromPeg,Integer tempPeg,Integer toPeg)
          //下语句是一个显示语句,不是指令语句,提示一个圆盘应从fromPeg 移动到 toPeg,显示中间移动过程
          Display "Move a disc from peg",fromPeg,"to peg",toPeg
          //下递归调用语句是一条指令,除一个圆盘之外,将所有圆盘从tempPeg 移动到 toPeg,将fromPeg作为临时存放处
          moveDiscs(Integer num-1,Integer tempPeg,Integer toPeg,Integer fromPeg)
    End if
End Module      

递归和循环
可以使用递归编码的任何算法也可以使用循环编码。这两种方法都要重复,但是递归算法肯定比循环算法效率低。每次调用一个函数或者模块,系统都需要额外的开销,而循环不需要这种开销。事实上,大多数重复性编程最好使用循环。
也有一些使用递归比使用循环更容易解决。例如,GCD公式的数学定义就适合递归方法。

参考:
[1]程序设计基础:原书第3版/(美) 托尼 加迪斯(Tony Gaddis)著;王立柱,刘俊飞译. 2018.4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值