算法 - 递归实现汉诺塔(The Tower of Hanoi)

2023-11-05

目录

引言:

分析:

分析两片汉诺塔的迁移过程:

 分析三片汉诺塔的迁移过程:

代码实现:

递归出口:

递归过程: 

完整程序代码:

运行结果:

参考资料:​​​​​


 

引言:

今天接触到了一个非常有意思的游戏,名字叫做汉诺塔(Tower of Hanoi),小时候没有玩过这个益智游戏,所以今天利用代码把这个益智游戏实现一下。在写汉诺塔的代码之前,我们先对汉诺塔的游戏规则、玩法、以及游戏过程进行了解:

汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

分析:

分析两片汉诺塔的迁移过程:

假设我们现在在A支柱有两个片子,分别为蓝色方框和红色反框,这是他们的初始状态:

​​​​​​​cc54b2a5a80e43d2a7fdc56323a8d4bc.png 

我们现在要将红色和蓝色方框按照原先的“大的在下面,小的在上面”的规则从A支柱迁移至C支柱,显然,我们要将蓝色方框先迁移至B支柱,然后将红色方框迁移至C支柱,然后再将蓝色方框从B支柱迁移至C支柱,这样就完成了迁移。

假设我们每次迁移的是支柱最上方的方框,迁移的顺序可以表示为:

A -> B

06411c7213d842228b36f61d043a5546.png

A -> C

38ac9c3eb0f64e4aa22c973f2862c6b7.png

B -> C

984690a71f6f4ad3bd71d6d34e58ea37.png

至此,两片的汉诺塔已经迁移完成。

 分析三片汉诺塔的迁移过程:

假设我们现在要迁移3片的汉诺塔,分别为红色方框、蓝色方框、黄色方框,这是他们的初始状态:

d1ec7b0d2039426491580c90b14a3985.png

按照上面每次迁移支柱最上面方框的规则,顺序可以表示为:

A -> C

f2d051e44a9b4738ab529fd329129c7f.png

A -> B

49c7a31b83374813ad1ac649bc8aa60b.png

C -> B

02d14875725948798016d95945bc4a87.png

A -> C

e87ed5bfceff47249a779301c155b552.png

B -> A

c1a1a84b037549c18b012bc1ee609163.png

B -> C

14913f231af44029aa9f059e71c2c79e.png

A -> C 

bcd7bf9f8c32419c95b08c532ba08186.png

至此,三片汉诺塔已经迁移完成。

那么接下来我们应该思考,从两片汉诺塔到三片汉诺塔我们能得出什么规律呢? 

我们发现,从三片汉诺塔的迁移过程来看,首先我们需要的就是将除了底部以上的方框先迁移到B支柱,将底部最大的方框释放并迁移至C方框,然后再将上面的两个方框依次放到最大方框的上面。也就是说,无论多少片的汉诺塔,我们都能把大的问题转化为小的问题。

例如,我现在要迁移四片的汉诺塔,首先我要考虑的就是如何将底部方框以上的三片进行正确的迁移且将底部方框迁移至目标支柱;

那么我在迁移三片汉诺塔的时候,要考虑的是不是将底部方框以上的两片进行正确的迁移且将底部方框迁移至目标支柱;

同样,我在迁移两片汉诺塔的时候,当然就是将上面的一片先迁移到目标支柱以外的B支柱,然后再将底部方框迁移至目标支柱,再继续将B支柱的方框迁移至C支柱从而完成整个迁移的过程。

我们可以用树状图来模拟这个将四片汉诺塔这个大问题逐步分解成三片、两片汉诺塔这种小问题的过程:

0e7aefc462b74728b73a44cea9370ef0.png

注:这里合并过程中的2,3,4 分别代表的是每一步对应的底部方框。 

代码实现:

经过上面对汉诺塔迁移过程的分析,大体的思路我们已经清楚,现在我们以递归方式实现汉诺塔的代码:

首先我们来设计递归函数,汉诺塔问题中涉及到的无外乎就是:汉诺塔上面的片子和三个支柱(分别为A、B、C),所以我们以这两个东西作为函数的形参:

void Hanoi(int n, char A , char B , char C);

递归出口:

既然要递归,我们首先应该考虑的就是递归出口,也就是当汉诺塔待迁移支柱上面的片数为1的时候,我们直接将这一片从待迁移支柱迁移至目标支柱,用代码来表示也就是:

if(n == 1){
        printf("%c -> %c\n",A,C);
    }

递归过程: 

我们假设现在有一个n片的汉诺塔待迁移,根据上面分析的分解和合并的过程,我们首先要做的就是将除了底层方框以外上面的所有方框迁移至B支柱,也就是将n - 1个方框绕过C支柱迁移至B支柱,用代码来表示就是:

Hanoi(n - 1,'A','C','B');

当我们将n - 1个方框成功迁移至B支柱的时候,下面我们应该考虑的就是将编号为n的底层方框迁移至目标支柱(C支柱),也就是 A -> C,用代码来表示就是:

printf("%c -> %c\n",'A','C');

接下来我们应该考虑的就是将B支柱上的方框依次迁移至C支柱,也就是将n - 1片绕过A支柱迁移至C支柱,用代码来表示就是:

Hanoi(n - 1,'B','A','C');

至此,n个方框的汉诺塔已经迁移完成。

完整程序代码:

#include<stdio.h>
void Hanoi(int n,char A,char B,char C)
{
    if(n == 1){
        printf("%c -> %c\n",A,C);
    }
    else{
        Hanoi(n - 1 , A,C,B);
        printf("%c -> %c\n",A,C);
        Hanoi(n - 1,B,A,C);
    }
}
int main()
{
    int n = 0;
    printf("Please enter the number of slice :");
    scanf("%d",&n);
    Hanoi(n,'A','B','C');
    return 0;
}

运行结果:

例如我在这里输入汉诺塔的方框数为3:

4b63ab275d3c4fcf99dd6cc7a244df30.png

运行结果的迁移过程和我们上方分析的三片汉诺塔的迁移过程完全一致,结果正确。 

参考资料:​​​​​​​​​​​​

百度百科 - 汉诺塔​​​​​​​

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

算法 - 递归实现汉诺塔(The Tower of Hanoi) 的相关文章

随机推荐

  • MFC之菜单栏的相关使用14

    1 菜单栏选项的打勾 加粗 禁用 首先我们需要知道菜单栏包含子菜单栏 依次使用下标去区分 然后拿到子菜单栏后 就可以操作里面的选项了 可以通过下标 选项的ID 在资源视图的菜单栏的图 点击选项右击属性即可获取 进行操作 代码 由于为了减少视
  • 【学习日志】【TCN】时间序列卷积神经网络(1)

    1 ask bing Temporal Convolutional Network 问 我对CNN RNN TCN等神经网络没有任何基础 你能直观地给我讲一下TCN的结构 输入输出和原理吗 bing对TCN的解释如下 TCN是一种用于处理序
  • C++标准库之IO库

    IO类 基本内容 iostream库包含两个基础类型 istream ostream cin 一个istream对象 用来从标准输入读取数据 cout 同cin cerr 用于输出程序错误信息 写到标准错误 方法 getline 从一个给定
  • 蓝桥杯大赛获奖选手,可获研究生推免加分啦,挺好的呀

    大家好 我是涛哥 我一直关注着各类大会和各类比赛 之前也写过蓝桥杯大赛的一些攻略 并用实际的题目和案例 为大家准备蓝桥杯比赛提供了指导 蓝桥杯大赛其实并不难 但好处很多 有的朋友可能对蓝桥杯还不太了解 不过没关系 我简单来跟大家说说 希望广
  • Java Double compare()方法具有什么功能呢?

    转自 Java Double compare 方法具有什么功能呢 下文笔者将讲述compare 方法的功能简介说明 如下所示 compare 方法的功能 java lang Double compare 方法的功能 用于比较两个基础类型的d
  • HTML5----响应式(自适应)网页设计(自动适应屏幕大小)

    HTML5 响应式 自适应 网页设计 自动适应屏幕大小 现在 很多项目都需要做响应式或者自适应的来适应我们不同屏幕尺寸的手机 电脑等设备 那么就需要我们在页面上下功夫 但移动端的布局不同于pc端 首先我们要知道在移动端中 css中的1px并
  • MyEclipse设置Java代码注释模板

    定义自己喜欢的模板注释 选中你要加注释的方法或类 按 Alt shift J 文件 Files 注释标签 Title file name Package package name Description todo author yok
  • 抓包工具mitmprox

    安装 我这里是在pycharm下项目setting安装的 设置环境变量 将下面exe这个路径添加至path 启动mitmproxy https blog csdn net shifengboy article details 1140672
  • 北邮22信通:实验五 共射放大电路的频率特性与深负反馈的影响

    北邮22信通一枚 很高兴以一个新身份与大家见面 关注作者 解锁更多邮苑模电实验报告 获取更多文章 请访问专栏 北邮22信通 电子电路 青山如墨雨如画的博客 CSDN博客 目录 实验目的 实验设备及器件 实验内容 1 频率特性分析 1 1 C
  • C# linq初探 使用linq查询数组中元素

    使用linq进行数组查询 输出数组中全部的偶数并升序输出结果 写法1 int numbers 5 10 8 3 6 12 查询的数组 var numqurey from num in numbers where num 2 0 按照条件过滤
  • 区间预测

    区间预测 MATLAB实现SARIMA季节性数据时间序列预测 arima函数 目录 区间预测 MATLAB实现SARIMA季节性数据时间序列预测 arima函数 预测效果 基本介绍 研究回顾 模型结构 程序设计 参考资料 预测效果 基本介绍
  • latex 基本用法(二)—— 矩阵(增广矩阵、长虚线)

    latex 基本用法 modm mod m mod modn pmod n pmod 1 增广矩阵 比如鸡兔同笼问题的线性方程组 x y 152x 4y 40 begin split x y 15 2x 4y 40 end split 首先
  • android 自定义控件--(圆盘形菜单控件)

    思路原理 定一个原点和一个半径 圆的四周均匀分布每个菜单 为了方便计算 菜单的坐标用度数表示 然后转化为极坐标计算 定某个点为起始点 根据总菜单数确定每个点增加的度数 然后依次确定每个点的度数 也就确定了坐标 源代码 package chr
  • linux下C语言修改文件权限

    头文件
  • Java 统计文本文件中字符数量

    设有一个文本文件word01 txt 内容如下 after a minute or two and said to his friend he opened them again a minute or two and said to fr
  • 【数据结构——树】Trie树的两种实现方式:二叉树(左孩子右兄弟)与二十六叉树

    输入 输入的第一行为一个正整数n 表示词典的大小 其后n行 每一行一个单词 不保证是英文单词 也有可能是火星文单词哦 单词由不超过10个的小写英文字母组成 可能存在相同的单词 此时应将其视作不同的单词 接下来的一行为一个正整数m 表示询问的
  • c++实现哈夫曼huffman压缩文本

    哈夫曼压缩原理就是构建二叉树 出现频率高的字母用更少的位数来表示 实现压缩的效果 比如字符串abcbbc 构建哈夫曼树 这样构建出编码表b gt 0 a gt 10 c gt 11 原本6个字符要48位来表示 现在只需要9位来表示即可 1
  • FairyGui简单介绍

    1 什么是FairyGui 跨平台UI编辑器 支持多种项目 如Unity Cocos2dx CryEngine HavokVision Starling Egret LayaAir Haxe Pixi LibGDX and More 2 a
  • 视频号的播放量和互动率、完播率密不可分

    如何提高视频号播放量 视频号是推荐机制 分两种 社交推荐 朋友给你点赞 我未关注也可能刷到你 和平台推荐 提高系统推荐的两个指标和一个逻辑 两个指标 互动率和完播率 1 互动率 互动率是指互动次数占总播放量的比重 包含 点赞率 评论率 转发
  • 算法 - 递归实现汉诺塔(The Tower of Hanoi)

    目录 引言 分析 分析两片汉诺塔的迁移过程 分析三片汉诺塔的迁移过程 代码实现 递归出口 递归过程 完整程序代码 运行结果 参考资料 引言 今天接触到了一个非常有意思的游戏 名字叫做汉诺塔 Tower of Hanoi 小时候没有玩过这个益