汉诺塔(Hanoi)问题归纳总结

article/2025/9/7 19:01:39

 一.汉诺塔问题及其递归算法

1.问题阐述

经典汉诺塔:

外文算法书对汉诺塔问题的描述:

2.算法步骤

三阶汉诺塔问题解题步骤

 共需7步。

四阶汉诺塔问题解题步骤

 共需15步

五阶汉诺塔问题解题步骤

可以清晰的看出分治思想以及递归过程

 算法采用了分治的思想,利用递归的方式,完成n层汉诺塔的移动。

问题解法:

当n=1时,只要将编号为1的圆盘从柱子A直接移到柱子C上即可。

n>1时,就需要借助另外一柱子来移动。将n个圆盘由A移到C上可以分解为以下几个步骤:

    (1)  将A柱子上的n-1个圆盘借助C柱子移到B柱子上;

    (2)  把A柱子上剩下的一个圆盘从A柱子移到C柱子上;

    (3)  最后将剩下的n-1圆盘借助A柱子从B柱子移到C柱子上。

假定n是盘的数量,T(n)是移动n个盘的移动次数。

当n=1时,T(1)=1

当n=2时,T(2)=2T(1)+1

当n=3时,T(3)=2T(2)+1

  • 递归关系式:

所以,n阶汉诺塔问题最少共需要2的n次方减1步

算法的时间复杂度为

 3.代码表示:

void  Hanoi(int numberOfDisks, char start, char destination ,char spare)
{//只有一个盘子时,从起始桩移到目标桩if (numberOfDisks == 1) {cout << "move the disk from peg 'start' to peg 'destination'<<endl;  }//超过一个盘子时else if(numberOfDisks > 1){Hanoi(numberOfDisks-1, start , spare , destination);     //将n-1个盘子移到过渡桩cout << "move top disk from peg 'start' to peg 'destination' << endl;   //将剩下的一个大盘移到目标桩Hanoi(numberOfDisks-1, start , destination , spare);  //将过渡桩的n-1个移到目标桩}
}

 二.汉诺塔问题的非递归算法

 汉诺塔问题也可以借助非递归算法来解决,有许多种非递归算法可以解决汉诺塔问题,博主认为最常见的是利用递归二叉树,下面列举两种非递归算法。

1.利用二叉递归树

文献[4]指出:汉诺塔问题的递归算法代码与二叉树的中序遍历算法代码十分相似,故采用了二叉树的中序遍历,发现汉诺塔问题的算法步骤正好可以画成一棵完全二叉树,其中序遍历过程就是汉诺塔问题的算法步骤。

函数move(N-1,s,e,t)  N:盘子数  ,s:起始桩   e:目标桩   t:过渡桩

 完全二叉树结点个数正好是2^n-1,与汉诺塔最优解法的步骤数相同

结点1到结点15正好对应4阶汉诺塔问题的15步

 要解决的问题:

(1)第i步(即结点i)应移动哪一盘片?

由图可知,同一层总是处理同一盘片,

第LN层各结点编号的最大公约数为2^(LN-1)

所以,求出第i步对应的LN,就能求出应该移动哪一盘片

文献[4]给出的方法是:

LN=1 ,j=2;      
cin>>i;
while(i%j==0)
{j*=2;LN++;
}例如i=12,12%2=0,所以j=4,LN=2;
12%4=0,所以j=8,LN=3;
12%8!=0,所以LN=3,结点i在第三层

知道第i步应该移动谁之后,还要知道从哪移到哪

(2)如何确定每一步盘片移动的起止桩编号?

  • 规律1:各层从左到右的第一个结点移动盘片时,起始桩编号都是1,目标是2或3(请看1,2,4,8四个结点)
  • 规律2:树的总层数N与结点i所在层数LN同奇或同偶时,目的桩为3,否则为2;
  • 规律3:由图可知,树的每一层内都有固定回路,有的是“1->3,3->2,2->1",有的是“1->2,2->3,3->1"。周期都为3。

那么只需要知道 :

1.所在层起始结点是哪种模式?(1->2还是1->3)

2.i在所在层的横向编号?(i是所在层从左到右的第几个结点)

3.i结点在循环回路中的第几个位置?(1/2/3)

  • 问题1:所在层起始结点是哪种模式?(1->2还是1->3)

设结点i所在层的起始结点的起止桩编号为(s,d)

由规律1、2,s=1,d=3-(N-LN)%2,假设i=11,则LN=1,d由前面公式算出等于2,

所以,i所在层最左侧结点开始为"1->2",则该层的循环回路为:“1->2,2->3,3->1"

  • 问题2:i是所在层从左到右的第几个结点?

设是第Sn个,Sn=Round(i/2LN)(Round为四舍五入),例如i=11,则LN =1,Sn由前面公式得出为6,那么i在第1层从左往右的第6个结点。

  • 问题3:i结点在循环回路中的第几个位置?

设在第p(1<=p<=3)个位置,p=(Sn-1)%3+1例如i=11,则LN =1,Sn=6,p由前面公式算出等于3,所以结点i在“1->2,2->3,3->1"循环的第三步,也就是“3->1"。

所以,如果问:汉诺塔问题的走法中,第i步应该移动谁?怎么移动?

根据上面公式,求出LN,d,Sn,p的值,就可以做回答

2.利用逆序编码

文献[5]采用了逆序编码的方式

两种编码方式

 3阶汉诺塔搬移:

 4阶汉诺塔搬移:

 去除4号盘的4层汉诺塔搬移顺序:

 发现4层汉诺塔搬移中,去掉4号盘之后,剩下的搬移路径与3阶汉诺塔完全相同

得出结论:

 完成 n 层汉诺塔的搬运,前 1,2,…,n-1 号圆盘的搬运次数、顺序与完成 n-1 层汉诺塔的搬运 相同。(只有在逆序编码时成立)

 其他定理与算法代码可以去文献[5]中阅读。

三.双色汉诺塔

采用数学归纳法

设f(n)为双色汉诺塔的移动规则,g(n)为普通汉诺塔的移动规则,n为圆盘个数。

很容易知:

      f(1) = g(1);

      f(2) = g(2);

      f(3) = g(3);

假设 f(k) = g(k) , f(k+1)=g(k+1)   若能证明f(k+2)=g(k+2),则结论得证

证明:

 

 所以可得出结论,双色汉诺塔问题与普通汉诺塔问题相同

四.利用启发式算法解决汉诺塔问题

1.A算法处理汉诺塔

f(n)=g(n)+h(n)

A算法搜索图及各函数意义

 关键在于估计函数h(n)的设计

一种设计方案是文献[7],

 设起始状态空间是I=<1,1,1>,目标状态空间是G=<3,3,3>,移动函数move(di,destination)。

设g=G0+G1+G2,评价函数设计为f(x)=g(x)+h(x),h(x)=| g - (d0+d1+d2) |

 发现此种方案只能保证找到解路径

文献[8]给出了另一种方案:

应用极值方法,考虑极端的情况,确定其上限和下限,把考虑对象限制在每个托盘中的最顶上的两个盘子。如果托盘中只有一个盘子,也没有关系,另一个盘子作为 0 处理;如果托盘中一个盘子都没有,那么最顶上的两个盘子都做 0 处理,这样不会影响结果。然后比较托盘 中最顶上两个盘子的权值的和,从而决定移动的方向。其移动的方向是:最小的权值之和的托盘移向具有较大的权值之和的托盘。

制定出以下几条规则:

  • 规则1:if(a0) if(A.top==1&&B.top==1) { move(B,C); move(A,C);}

                     else { if(!move(A,B)) move(A,C);}

  • 规则2:if(a==0&&b<c)   if(!move(C,A)) move(B,A);
  • 规则3:if((a==b)>c&&c!=0) if(!move(C,B)) move(C,A);
  • 规则4:if(a>b&&b==c) if(!move(C,B)) move(B,C)

 如上图,过程1运用了规则2,过程2运用了规则2,过程3运用了规则1,过程4运用了规则2,过程5运用了规则4,过程6运用了规则3,过程7运用了规则2,过程8运用了规则1,过程9运用了规则2,过程10运用了规则2。

2.利用问题规约法

 方法与分治类似

 画出每一步的状态空间图,图中的弧线代表逻辑或关系

参考文献:

文献[1] Ames W F . Computer Algorithms — Introduction to design and analysis (second edition)[J]. Mathematics and Computers in Simulation, 1990, 31(6):602-602.

文献[2] 手撕“汉诺塔算法”之详细图解_灰小猿的博客-CSDN博客_汉诺塔算法  

三阶汉诺塔问题算法步骤图来自文献[2]

文献[3] b站视频 【汉诺塔小游戏和递归思想】 https://www.bilibili.com/video/BV1Zh411y7XB?share_source=copy_web&vd_source=fa7199f346f857b079aeb8f19090512c    (5阶汉诺塔问题图像来源)

文献[4] 彭伟.汉诺塔问题的非递归算法设计及可视化实现[J].武汉船舶职业技术学院学报,2011,10(06):55-59+72.

文献[5] 严海兵.基于逆序编码的汉诺塔非递归算法[J].苏州科技大学学报(自然科学版),2022,39(01):71-76.

文献[6] 王晓东. 计算机算法设计与分析-第 3 版[M]. 北京: 电子工业 出版社,2009.

文献[7] [AI]A*搜索练习题——3传教士3食人族、单臂机器人、汉诺塔_是土豆大叔啊!的博客-CSDN博客

文献[8] 陈炼,邓少波,万芳.A算法在梵塔问题中的应用[J].计算机工程,2005(08):168-170. 


http://chatgpt.dhexx.cn/article/1cfFfD7Z.shtml

相关文章

汉诺塔问题(Hanoi)

汉诺塔问题&#xff0c;是心理学实验研究常用的任务之一。该问题的主要材料包括三根高度相同的柱子和一些大小及颜色不同的圆盘&#xff0c;三根柱子分别为起始柱A、辅助柱B及目标柱C。 相传在古印度圣庙中&#xff0c;有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置…

经典递归算法——汉诺塔问题

一、问题背景简介 相传在古印度圣庙中&#xff0c;有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上&#xff0c;有三根杆(编号A、B、C)&#xff0c;在A杆自下而上、由大到小按顺序放置64个金盘(如图1)。游戏的目标&#xff1a;把A杆上的金盘全部移到C杆上&#xff…

【C语言】递归详解汉诺塔问题

文章目录 前言汉诺塔移动图解汉诺塔移动次数汉诺塔的打印结语 如果无聊的话&#xff0c;就来逛逛 我的博客栈 吧! &#x1f339; 前言 汉诺塔&#xff0c;是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子&#xff0c;在一根柱子上从下往上按照大小…

Linux基本操作---实践+理解--CentOS 7

目录 CentOS系统ls查看信息cd目录切换文件操作系统关闭/重启防火墙操作 CentOS系统 Linux系统有很多&#xff0c;常见的Linux系统有乌班图&#xff08;Ubuntu&#xff09;、深度&#xff08;deepin&#xff09;、CentOS等等&#xff0c;CentOS 7 是目前比较流行的Linux操作系统…

Linux 文件操作基本命令

在Linux文件操作中&#xff0c;最常用的基本命令包括&#xff1a;打开或者创建文件&#xff0c;写入文件&#xff0c;读取文件 下面将依次介绍这几种操作的常用方法。 1.打开/创建文件 首先说明在VI编辑模式中&#xff0c;若要使用该API&#xff0c;需包含相应的头文件&…

Linux基本操作命令 实验

一、实验目的&#xff1a; 1. 熟悉Linux基本命令。 2. 熟悉Linux操作系统。 二、实验环境&#xff1a; 一台装有Linux的机器。 三、实验内容&#xff1a; 1.文件操作命令的使用。 用vi编辑器新建一个testl文件 输入this is testl~&#xff01; 查看文件与目录ls 进入…

linux的基本操作命令

1.使用timedatectl查看时间状态 列出所有已知时区 修改时区为列出时区的某一个 首先打开linux系统&#xff0c;进入管理员模式&#xff0c;输入timedatectl [rootroot ~]# timedatectl Local time: Sun 2022-03-20 17:26:05 CSTUniversal time: Sun 2022-03-20 09:26:05 …

Linux实验一:熟悉Linux基本命令

【实验目的】 ‏(1)熟悉常用的文件和目录类命令。 ‏(2)熟悉常用的进程管理类命令。 ‎ ‏【实验要求】 ‎ 本实验的主要任务是在Linux终端窗口中练习已经学过的各种命令&#xff0c;熟练掌握常用命令的用法。清大家按照以下步骤完成本次实验。 ‏(1)以普通用户登录系统&…

linux配置网口的ip地址,Linux基本操作和基础命令(Linux修改IP地址以及修改网卡地址)...

Linux基本操作和基础命令(Linux修改IP地址以及修改网卡地址) 今天博主和大家聊一聊 Linux的基本操作&#xff0c;不喜勿喷&#xff0c;如有建议欢迎补充&#xff0c;讨论。 一.Linux网络 1.网卡的命名规则 CENTOS7采用dmidecode采集命名方案&#xff0c;以此来得到主板信息&…

Linux基本命令及编程环境实验

目录 一、Linux基本命令详细汇总 1、目录及文件相关命令 2、系统信息查询 3、文件操作&#xff08;统计、过滤、搜索、权限&#xff09; 4、其他命令 二、Linux终端上vi命令编程 1、进入vi命令模式 2、vi编辑模式 3、最后行模式 4、vi 编辑C源程序并编译运行 最后 一…

linux基本命令大全

基本命令 关机&#xff1a;shutdown -h halt init 0 poweroff 重启&#xff1a;shutdown -r reboot init 6 pwd&#xff1a;查看工作目录 ls&#xff1a;查看指定目录的内容 -l&#xff1a;列表显示 -a&#xff1a;显示所有&#xff0c;包括隐藏文件 -h&#xff1a;人性化的显示…

linux用户基本操作

用户的管理 1.创建一个新用户user1 ,设置其主目录为/home/use1 useradd user1 -d /home/user12.查看/etc/passwd文件的最后一行&#xff0c;看看如何记录 vim /etc/passwd3.查看文件/etc/shadow文件的最后一行 vim /etc/shadow4.给用户设置密码 passwd user1 123456//密码…

linux课程--实验一 Linux 基本命令操作1

一、实验目的&#xff1a; (1)掌握Linux各类命令的使用方法。 (2)熟悉Linux字符界面操作环境。 二、实验准备 (1)了解Linux命令行的基本概念。 (2)自己建立目录结构以及目录下的文件。 三、实验过程&#xff08;内容包括&#xff1a;&#xff08;1&#xff09;练习linux命…

操作系统实验一 Linux基本操作|实验二 进程管理

由于当时没存代码&#xff0c;只有实验文档代码截图&#xff0c;文末也可直接获取实验文档。 操作系统实验 目录 实验一 Linux基本操作实验二进程管理 实验一 Linux基本操作 1实验目的 1.熟悉在Linux操作系统下的基本操作&#xff0c;对Linux操作系统有一个感性认识。 2.学…

Linux系统介绍及熟悉Linux基础操作

一、什么是Liunx Linux&#xff0c;全称GNU/Linux&#xff0c;是一种免费使用和自由传播的类UNIX操作系统&#xff0c;其内核由林纳斯本纳第克特托瓦兹&#xff08;Linus Benedict Torvalds&#xff09;于1991年10月5日首次发布&#xff0c;它主要受到Minix和Unix思想的启发&am…

操作系统——实验一(Linux基本操作)

操作系统——实验一(Linux基本操作) &#xff08;1&#xff09;练习Linux的基本安装和配置&#xff1b; &#xff08;2&#xff09;以root用户身份登陆&#xff0c;并使用“ls”,“cat”“cd”等常用命令来实现基本的文件操作并观察Linux文件系统的特点&#xff1b; &#xff…

Linux系统基础操作命令

目录 一、基本使用 1.编辑Linux命令行的辅助操作 2.常用的基础命令 1.切换用户&#xff08;su&#xff09; 2.pwd 查看当前工作目录 3.cd 切换工作目录 4.cp 复制 5.mkdir 创建目录 6.touch 创建文件 7.创建链接文件ln&#xff08;软链接、硬链接&#xff09; 8.alia…

Linux的基本操作

Linux的基本操作 文章目录 Linux的基本操作cd命令ls命令pwd命令touch命令cat命令mkdir命令rm命令cp命令mv命令man命令less命令head命令tail 命令date命令grep命令ps命令netstat命令 cd命令 语法&#xff1a;cd 目录名 功能&#xff1a;改变当前所在目录&#xff0c;将当前工作…

Linux基本操作之vi编辑器

Linux基本操作之vi编辑器 一、Vi编辑器的启动和退出启动退出 二、Vi编辑器的工作模式编辑模式插入模式命令模式 三、Vi编辑器的基本命令文件相关命令字符串搜索、替换和删除文本的复制、删除和移动 四、C/C编辑器gcc的使用1.编写代码2.使用命令编译和运行 一、Vi编辑器的启动和…

LINUX的基本操作学习总结

前言 从2020年11月定下了以后所打算从事的方向开始&#xff0c;就开始学习LINUX基础和LINUX环境编程&#xff0c;故谨以此文来记录LINUX的基础操作 声明&#xff1a;因个人能力有限&#xff0c;本文仅是个人的学习记录笔记&#xff0c;有错误之处还望指出 目录 1.LINUX的基础…