汉诺塔递归算法精讲

news2024/10/1 5:53:42

文章目录

  • 前言
  • 一、汉诺塔是个啥?
  • 二、手动解法
  • 三、解法抽象
  • 四、递归解法
  • 五、总结


前言

递归算法是计算机算法中的基础算法,也是非常重要的算法,从某种程度上讲,它有一点儿AI的影子。人脑是可以完成递归思路的,但是对不起,残酷的现实是,一般人脑在精力集中的情况下,能递归个三五层就就基本晕菜了。反正我是这样,你或者您可能深度多一些。当然个别领域,例如棋手,可能深度多达10层或者20层,这是凤毛麟角了。

废话少说,说说汉诺塔的递归解法思路,并给出本人朴素的解释,力图使一看就晕的小伙伴们,能看清楚。


一、汉诺塔是个啥?

尽管您或许知道这个小游戏,但是为了将问题说清楚,还是要简单介绍一下。以下内容来自 《百度百科》

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

二、手动解法

下面尝试用静态图来分析和描述一下手动解法,大家也可以参考下列链接,以期获得感性认识。
汉诺塔在线游戏
为了简便起见,我们从三个开始尝试。
如图:
在这里插入图片描述
根据题目要求,每次移动一个,而且必须是小的在上面。如果胡乱尝试,您可能好会成功,但是可能会不得要领,因此先分析,才能厘清思路。
分析:我们考虑最后一步,必然是将 1 从什么地方 移到 C 上,倒数第二步,必然是将2 从什么地方移到C上,倒数第三步必然是将3 从什么地方移到C上。因为3 最大,因此,倒数第三步时,必然是3的上面没有盘子,C的上面没有盘子。否则就违背了原则,因此,如果想办法通过什么方法变成下面的情况,倒数第三步就实现了。
如图:
在这里插入图片描述
此时就可以把 3 移到 C上,如图
在这里插入图片描述
冷静一下,你会发现,此时问题已经降级为,如何将两个盘子移到C上的问题,只是位置从A 变成了B,聪明的你,可以知道这并没有区别。所以现在的问题是 怎么将两个盘子移到到C上。这个问题就非常简单了,1->A, 2->C,1->C。 由于我们遵守小的在上面的原则,就是说每次只能取最上面的 一个 盘子,因此上面的步骤也可以用位置来表示就是
B->A, B->C, A->C, 至于上面的盘子是啥,其本身已经记住了。
OK, 三个已经完成了。

三、解法抽象

现在我们整理一下思路:
要想把3个盘子从A移到C上,必须先把3-1个盘子从A移到B上;套用上面的想法,
做进一步的思考:如果想把3-1个盘子从A移到B上,必需先把 3-1-1个盘子从A移到C上。
仔细看上面的步骤,我们进一步分析其细节,把语言可以精确的描述为:

要想把3(n)个盘子从A 移到C上,必须先把3-1(n-1)个盘子通过C移到B上;
如果想把3-1(n-1)个盘子从A移到B上,比需先把 3-1-1(n-1-1)个盘子通过B移到C上。
可以看出上述的步骤的相似性,就是有三个抽象点,第一:起点, 第二 终点, 第三是:过度点。

仿照上面的思路,我们可以得到 n个盘子的移动方法;
要想把n个盘子移到C上,必须先把n-1个盘子通过C移到B上;
采用更抽象的描述就是:
要想把n个盘子从 起点 移到 终点上,必须先把n-1个盘子通过 终点 移到 过渡点上;
我们用 From 表示起点,To 表示终点 , By 表示过渡点,那么上面的描述就是

要想把n个盘子从from 移到 to ,必须先把n-1个盘子通过 to 移到 by 上;

进一步,假设我们完成了一个过程,叫 HanoiMove, 根据上面的分析,它必须包括四个关键属性: 个数n,起点 from,过渡点 by,终点 to,我们不妨记作

HanoiMove(n,from, by, To) ,这个表示 把 n 个盘子从From 经过 by, 移到到 To,聪明的你应该看出来这不就是函数吗?为了更清楚起见,我们采用 相应的位置表示起点,过渡点和终点。

四、递归解法

根据上面的分析,我们只要逐层降级就可以完成任务了,这就用到了递归,为了说清楚,我们慢慢来。

第一步:调用 HanoiMove(n,from, by, To) ,表示将n从 From 经过 by 移到 To 上。

第二步:HanoiMove(n-1,from, by, To ) ,这个表示 将n-1个盘子,从 from 经过to移到 by 上

第三步:此时From 上面只有一个 最大号的 盘子了 ,编号n,只需 将 编号n的盘子从 From 移动到 to上就可以了。注意此时是移动一个盘子,没有递归的问题。

第四步:这个时候, n-1个盘子 在 by 上面(by成为起点了,from 是过渡点, to仍然是终点), 调用前面的过程 HanoiMove(n-1,by, from, to ) 这个表示 将n-1个盘子,从 by 经过From移到 to上

到这一步就完成了所有的盘子的搬运。

写成伪代码的函数就是:

HanoiMove(n,from, by, To){
	HanoiMove(n-1,from, by, To ) 
	输出:From->to
	HanoiMove(n-1,by, from, to )

}
但是这样就行了吗?
递归调用的一个关键就是结束条件,如果没有,就会一直递归下去,直到溢出错误出现。上面的伪代码中,没有结束条件,那么结束条件是什么呢?显然是n=1 的时候,就结束了。因此,加上结束条件之后的代码为:

HanoiMove(n,from, by, To){
	if(n==1) {
		输出:From->to
		  return 
	}
	HanoiMove(n-1,from, by, To ) 
	输出:From->to
	HanoiMove(n-1,by, from, to )

}
可以将上述伪代码,改编成某种语言运行

其C#代码如下:

       public void HanoiMove(int n, string from, string by, string to)
        {

            if (n > 1)
            {
         
                HanoiMove(n - 1, from , to, by);
                Console.WriteLine( String.Format("\r\n{0} {1}->{2}", n, from, to));//是盘子编号,可以不用。
                HanoiMove(n - 1, by, from, to);
            }
            else
            {
               Console.WriteLine( String.Format("\r\n{0} {1}->{2}", n, from, to));
            }
        }

注意:上面的输出的n 可以不用。


五、总结

对于递归调用的代码实现,一定要将过程抽象出来,反复的在头脑中进行这一过程的拟合,将具体步骤进行高度的抽象,具化成参数和表达式(输出),并设置结束条件(递归出口)。

MaraSunDB BJFWDQ 2023-02-15

`

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/348202.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《爆肝整理》保姆级系列教程python接口自动化(十五)--参数关联接口(详解)

简介 我们用自动化新建任务之后,要想接着对这个新建任务操作,那就需要用参数关联了,新建任务之后会有一个任务的Jenkins-Crumb,获取到这个Jenkins-Crumb,就可以通过传这个任务Jenkins-Crumb继续操作这个新建的任务。 …

自适应布局之淘宝无限适配+rem+微信rpx自适应

一、自适应布局 所谓前端适配,就是为了让移动设计稿在大部分的移动设备上看起来有一致的展示效果,目前比较流行的方法有两种。一种是强制meta viewport宽度为设计稿宽度,一种是使用rem自适应布局的flexible.js。 二、当前流行的移动端自适应…

【刷题笔记】--盛最多水的容器--双指针

题目: 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明:你不…

Python 高级编程之正则表达式(八)

文章目录一、概述二、正则表达式语法1)字符匹配2)字符集合3)定位符4)分组1、定义分组2、引用分组3、命名分组三、Python 的 re 模块1)re.match() 方法2)re.search() 方法3)re.match() 与 re.sea…

2023最牛教程,手把手教你成为年薪30W的测试开发

随着互联网行业的高速发展,快速高质量的产品版本迭代成为企业始终立于不败之地的迫切需求,而在短期迭代的快节奏中,传统测试工作面对更大压力,无法持续提供高效率高质量的人力支撑,所以越来越多的企业需要技术更为全面…

Leetcode-每日一题1250. 检查「好数组」(裴蜀定理)

题目链接:https://leetcode.cn/problems/check-if-it-is-a-good-array/description/ 思路 方法:数论 题目意思很简单,让你在数组 nums中选取一些子集,可以不连续,子集中的每个数再乘以任意的数的和是否为1&#xff…

netty

Netty的介绍Netty是异步的(指定回调处理)、基于事件驱动的网络应用框架,用于快速开发高性能、高可靠性的网络IO程序。Netty本质是一个NIO框架,适用于服务器通讯相关的多种应用场景,分布式节点远程调用中Netty往往作为R…

RTT 消息邮箱

1.邮箱概念 邮箱服务是实时操作系统中一种典型的线程间通信方法。举一个简单的例子,有两个线程,线程 1 检测按键状态并发送,线程 2 读取按键状态并根据按键的状态相应地改变 LED 的亮灭。这里就可以使用邮箱的方式进行通信,线程 …

SpringCloud保姆级搭建教程五---Redis

首先,这个和微服务没有直接的关系,只是在代码开发当中要使用的一个工具而已,为了提高这个系统的性能,加快查询效率等方面而使用它1、首先,要先安装redis到电脑上,这里依然是在windows上演示,之后…

window11, WSL, Ubuntu 20.04 编译TensorRT源码并且安装 TensorRT

一、安装参考 1.ubuntu18.04TensorRT 配置攻略 ubuntu18.04TensorRT 配置攻略 - 简书卷积网络的量化和部署是重要环节,以前我们训练好模型后直接trace进行调用,参考(C windows调用ubuntu训练的PyTorch模型(.pt/.pth)…

Utkuici:一款功能强大的Nessus自动化任务实现工具

关于Utkuici 今天,随着信息技术系统的普及,网络安全领域的投资已大幅增加。各种规模的组织都需要进行漏洞管理、渗透测试和各种分析,以准确确定各自机构受网络威胁的影响程度。通过借助漏洞管理工具的行业领先者Tenable Nessus,我…

若依ruoyi——手把手教你制作自己的管理系统【三、代码生成】

昨天情人节一( ̄︶ ̄*)) 送给赛利亚一((* ̄3 ̄)╭ ********* 专栏略长 爆肝万字 细节狂魔 请准备好一键三连 ********* 修改后的页面: 干干净净贼舒服一Ψ( ̄∀ ̄)Ψ——Ψ( ̄∀&#x…

Vue一个项目兼容每个省份的个性化需求

开发环境及打包指令 后拼上省份区划"serve:henan": "yarn && vue-cli-service serve -o --encryptSM2 --zone41","serve:hunan": "yarn && vue-cli-service serve -o --encryptSM2 --zone43","serve:guizhou&quo…

电子技术——多阶放大器

电子技术——多阶放大器 实际上的商用放大器是由多个单阶放大器联级而成的多阶放大器。首先第一阶(输入)通常提供一个较大的输出阻抗来保证较小的信号衰减。若是差分放大器,还要保证有较大的共模抑制比。中间各阶放大器负责提供电压增益&…

wireshark在流媒体分析中常见操作

Wireshark Wireshark(前称Ethereal)是一个网络封包分析软件。网络封包分析软件的功能是截取网络封包,并尽可能显示出最为详细的网络封包资料。Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换。 在流媒体相关工作中&am…

学英语的优势已来,抓住这个机会

文 / 冰雪(微信公众号:王不留) ChatGPT大火,国外的商业价值还没找到,咱们这边已经开始变现了。谷雨小姐姐昨天在”一起学英语”微信群发了一张“收割韭菜”的文案截图。 299入社群,服务内容为:免…

卷严重、难度高、激励少,如何适应空投市场新变化

自从空投交互从2020年开始之后,不少人都开始加入到空投交互的行列中,一些项目也因为“格局”的因素,在项目正式上线前都会给早期参与者空投代币,以此吸引大家的关注。但是在越来越多的人加入到撸空投行列之中后,现在整…

javaEE 初阶 — 流量控制与拥塞控制

文章目录1. 流量控制2. 拥塞控制TCP 工作机制:确认应答机制 超时重传机制 连接管理机制 滑动窗口 1. 流量控制 流量控制是一种干扰发送的窗口大小的机制,滑动窗口,窗口越大,传输的效率就越高(一份时间,…

Gromacs中的g_mmpbsa计算带电底物与蛋白的结合能不准确

g_mmpbsa计算带电底物与蛋白的结合能总是不准确 TOC 在做的两个项目中,利用g_mmpbsa计算带电底物与蛋白的结合能结果非常不可靠,底物带两个硫酸根离子,g_mmpbsa在计算带电的底物与酶的结合能时总是不准确,因此后续若底物带电&…

三层交换机DHCP中继

关于中继,我们需要有一个对比。正常情况下我们是不是需要配置单臂路由然后开启DHCP地址池,然就设置网段网关以及DNS。这样的话考验 的其实是命令功底。但是为了方便,我们 可以添加服务器,将这个服务给到服务器去配置,这…