汉罗塔问题(递归)

article/2025/6/22 0:21:39

数据结构–汉罗塔

题目描述

在这里插入图片描述

在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制:
1.一次只能移动一个圆盘.
2.每个步骤都包括从一座塔中取出上部圆盘并将其放在另一座塔的顶部或空的柱子上.
3.不能将较大的圆盘放置在较小的圆盘上.

先上代码:

#include <stdio.h>void hanoi(int paraN, char paraSource, char paraDestination, char paraTransit) {printf("paraN is %d, paraN address is %d, paraSource address is %d,paraDestination address is %d, paraTransit address is %d\r\n",paraN, &paraN, &paraSource, &paraDestination, &paraTransit);//打印此时汉罗塔盘子的个数以及和各个柱子的地址if (paraN <= 0) {return;} else {hanoi(paraN - 1, paraSource, paraTransit, paraDestination);printf("%c -> %c \r\n", paraSource, paraTransit);hanoi(paraN - 1, paraDestination, paraSource, paraTransit);}
}void hanoiTest() {printf("---- addToTest begins. ----\r\n");printf("2 plates\r\n");hanoi(2, 'A', 'B', 'C');printf("3 plates\r\n");hanoi(3, 'A', 'B', 'C');printf("---- addToTest ends. ----\r\n");
}int main() {hanoiTest();
}

运行结果:

D:\study.clion\untitled7\cmake-build-debug\untitled7.exe
---- addToTest begins. ----
2 plates
paraN is 2, paraN address is 6421968, paraSource address is 6421976,paraDestination address is 6421984, paraTransit addr
ess is 6421992
paraN is 1, paraN address is 6421904, paraSource address is 6421912,paraDestination address is 6421920, paraTransit addr
ess is 6421928
paraN is 0, paraN address is 6421840, paraSource address is 6421848,paraDestination address is 6421856, paraTransit addr
ess is 6421864
A -> B
paraN is 0, paraN address is 6421840, paraSource address is 6421848,paraDestination address is 6421856, paraTransit addr
ess is 6421864
A -> C
paraN is 1, paraN address is 6421904, paraSource address is 6421912,paraDestination address is 6421920, paraTransit addr
ess is 6421928
paraN is 0, paraN address is 6421840, paraSource address is 6421848,paraDestination address is 6421856, paraTransit addr
ess is 6421864
B -> C
paraN is 0, paraN address is 6421840, paraSource address is 6421848,paraDestination address is 6421856, paraTransit addr
ess is 6421864
3 plates
paraN is 3, paraN address is 6421968, paraSource address is 6421976,paraDestination address is 6421984, paraTransit addr
ess is 6421992
paraN is 2, paraN address is 6421904, paraSource address is 6421912,paraDestination address is 6421920, paraTransit addr
ess is 6421928
paraN is 1, paraN address is 6421840, paraSource address is 6421848,paraDestination address is 6421856, paraTransit addr
ess is 6421864
paraN is 0, paraN address is 6421776, paraSource address is 6421784,paraDestination address is 6421792, paraTransit addr
ess is 6421800
A -> C
paraN is 0, paraN address is 6421776, paraSource address is 6421784,paraDestination address is 6421792, paraTransit addr
ess is 6421800
A -> B
paraN is 1, paraN address is 6421840, paraSource address is 6421848,paraDestination address is 6421856, paraTransit addr
ess is 6421864
paraN is 0, paraN address is 6421776, paraSource address is 6421784,paraDestination address is 6421792, paraTransit addr
ess is 6421800
C -> B
paraN is 0, paraN address is 6421776, paraSource address is 6421784,paraDestination address is 6421792, paraTransit addr
ess is 6421800
A -> C
paraN is 2, paraN address is 6421904, paraSource address is 6421912,paraDestination address is 6421920, paraTransit addr
ess is 6421928
paraN is 1, paraN address is 6421840, paraSource address is 6421848,paraDestination address is 6421856, paraTransit addr
ess is 6421864
paraN is 0, paraN address is 6421776, paraSource address is 6421784,paraDestination address is 6421792, paraTransit addr
ess is 6421800
B -> A
paraN is 0, paraN address is 6421776, paraSource address is 6421784,paraDestination address is 6421792, paraTransit addr
ess is 6421800
B -> C
paraN is 1, paraN address is 6421840, paraSource address is 6421848,paraDestination address is 6421856, paraTransit addr
ess is 6421864
paraN is 0, paraN address is 6421776, paraSource address is 6421784,paraDestination address is 6421792, paraTransit addr
ess is 6421800
A -> C
paraN is 0, paraN address is 6421776, paraSource address is 6421784,paraDestination address is 6421792, paraTransit addr
ess is 6421800
---- addToTest ends. ----进程已结束,退出代码0

分析

以下分为七个部分

1.自顶向下,逐渐求精:

​ 汉罗塔问题的求解方式为自顶向下,逐渐求精。也就是说,若现在有n个盘子,要将这n个盘子从a柱子移动到c柱子,那么我们就可以先把n-1个盘子从a柱子移动到b柱子,然后将第n个柱子移动到c柱子,最后再将那n-1个柱子从b’柱子移动到c柱子上。对于那n-1个盘子,则需要将n-2个盘子从a柱子移动c柱子,再将第n-1个盘子从a柱子移动到b柱子,最后再将那n-2个盘子从c柱子移动到b柱子上…以此类推,可以看出,这里有三个子问题,这三个子问题的思路一致,所以可以用递归来解决。

2.函数调用、递归与分治:

为了解决汉罗塔问题,在上述我们也说了,需要用到递归的方法。具体点说,我们需要编写一个函数,就是上面代码中的void hanoi(int paraN, char paraSource, char paraDestination, char paraTransit);函数。其中paraN表示要移动的圆盘个数,后面三个分别 表示a,b,c柱子。

3.形参与实参:

在函数调用过程中,我们使用形参来表示函数的输入参数,而实参则是在函数调用时提供的具体数值。在汉诺塔问题中,形参 paraN、paraSource、paraDestination和 paraTransit分别表示要移动的圆盘数和三个柱子。在函数调用时,我们需要提供实际的圆盘数和三个柱子的具体名称,如 void hanoi(int paraN, char paraSource, char paraDestination, char paraTransit)。

4.有意义、规范的标识符:

在编写程序时,使用有意义、规范的标识符可以使代码更易于理解和维护。也就是命名规范。

5.时间复杂度:

汉诺塔问题的时间复杂度为 O(2^n)。n表示有n个盘子。

    if (paraN <= 0) {return;} else {hanoi(paraN - 1, paraSource, paraTransit, paraDestination);printf("%c -> %c \r\n", paraSource, paraTransit);hanoi(paraN - 1, paraDestination, paraSource, paraTransit);}

设盘子个数为n时,需要T(n)步,把A柱子n-1个盘子移到B柱子,需要T(n-1)步,A柱子最后一个盘子移到C柱子一步,B柱子上n-1个盘子移到C柱子上T(n-1)步。
得递推公式T(n)=2T(n-1)+1
所以汉诺塔问题的时间复杂度为O(2^n);

6.递归栈:

递归函数的调用过程需要使用递归栈来保存每个函数调用的状态。在汉诺塔问题中,每个递归调用会创建一个新的函数调用帧,并将其压入递归栈中。当递归调用返回时,对应的函数调用帧会被弹出,恢复到上一层调用的状态。因此,在解决汉诺塔问题的过程中,递归栈的深度等于递归调用的层数,即 n。

7.空间复杂度:

汉诺塔问题的空间复杂度为 O(n),其中 n 是圆盘的数量。

接下来我会以三个盘子为例来讲解。我们把实现汉罗塔的代码单独拿出来说
在这里插入图片描述

第一步:我们要先将a柱子上的前两个移动到b柱子上

第二步:我们将a柱子上第三个盘子移动到c柱子上

第三步:将b柱子上的两个盘子移动到c柱子上

当然 我相信伙伴们应该想不明白上面两个盘子怎么移。其实和上述一样。现在我们单独来看前两个盘子,因为第三个盘子是最大的,所以移动前两个盘子的时候不必考虑盘子的大小。在移动前两个盘子的时候,也是要先将第一个盘子先移到c柱子上,然后再将第二个盘子移动到b柱子上,最后再将第一个盘子从c柱子移到b柱子。这样一看是不是和上面的步骤大体一致?所以我们可以写成递归的形式。

无论多少个盘子,就像是n个,都是先将n-1个盘子先从a柱子移动到b柱子,再将第n个盘子移动到c柱子,最后将这n-1个盘子从b柱子移动到c柱子。这样就完成了盘子的移动。

hanoi(paraN - 1, paraSource, paraTransit, paraDestination);
printf("%c -> %c \r\n", paraSource, paraDestination);
hanoi(paraN - 1, paraTransit, paraDestination, paraSource);

所以小伙伴们应该可以理解这三句代码了。

注意:

用递归就一定要有退出条件。在这里,递归的退出条件就是paraN=0。当paraN=0时,就没有盘子在上面了,当然也就没有办法移动了。

文章来源:https://blog.csdn.net/m0_74263898/article/details/130308167
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://chatgpt.dhexx.cn/article/fo0m99xQ.shtml

相关文章

多柱汉罗塔(python解法,带注释,注释为个人理解)

一、参考链接&#xff1a; 1、普通汉罗塔链接&#xff08;这边也是我的博文&#xff09;&#xff1a; (166条消息) 递归经典算法案例题&#xff08;汉罗塔、阶乘、斐波那契代码&#xff09;_南风~古草的博客-CSDN博客_汉罗塔 2、大佬的多柱汉罗塔博文&#xff08;有数学推…

累加—递归汉罗塔问题 (C语言)

一、累加—递归 一、代码 二、测试结果 二、汉罗塔问题 一、分析 二、代码 三、测试结果 三、总结 一、累加—递归 一、代码 //累加的递归实现 #include <stdio.h>int addTo(int n) {if(n < 0)return 0;else{return addTo(n-1)n;} } void addToTest() {int n…

【C语言】汉罗塔

前言 &#x1f388;大家好&#xff0c;我是何小侠&#x1f388; &#x1f300;大家可以叫我**小何或者小侠&#x1f300;** &#x1f534;我是一名普通的博客写作者&#x1f534; &#x1f490;希望能通过写博客加深自己对于学习内容的理解&#x1f490; &#x1f338;也能帮助…

[C语言]C语言解决汉罗塔问题(初学者版)

目录 1、汉罗塔问题解决思路&#xff1a; 2、代码实现&#xff1a; 函数部分&#xff1a; 全部代码&#xff1a; 运行结果&#xff1a; 3、结语&#xff1a; 1、汉罗塔问题解决思路&#xff1a; 以三个为例&#xff0c;步骤为&#xff1a; 1.首先我们需要将其分成两个整体…

汉诺塔问题的详细讲解(python版)

2022.3.17 2022.11.15 增加次数计算一&#xff0e;抽象为数学问题&#xff1a; 从左到右有A、B、C三根柱子&#xff0c;其中A柱子上面有从小叠到大的n个圆盘&#xff0c;现要求将A柱子上的圆盘移到C柱子上去&#xff0c;期间只有一个原则&#xff1a;一次只能移到一个盘子且大…

Golang 汉罗塔问题

先用一般方法实现汉罗塔方法: 先确定三个"石柱" A B C 。n代表A柱起始圆盘数量 主函数: 结合栈来实现汉罗塔。 因为栈先进后出的特点 很适合汉罗塔。其实和上述方法本质一样,只不过添加了 栈的特性 这里定的栈最大容量为7,可以根据实际情况更改 栈的构造&#xff…

汉罗塔(递归分治)

Java代码如下 public class Hanoi {//操作步骤数private static int steps 1;public static void main(String[] args) {//盘子数目int diskNumber 4;doTowers(diskNumber, A, B, C);}private static void doTowers(int diskNum, char from , char via, char to){if (diskNum…

汉诺塔(Hanoi)问题,Java实现,C语言实现,Python实现!!!

目录 一、汉诺塔的玩法 二、汉诺塔的逻辑 三、代码实现 四、运行结果 五、总结 一、汉诺塔的玩法 汉诺塔&#xff08;Tower of Hanoi&#xff09;&#xff0c;又称河内塔&#xff0c;是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子&#x…

Java基础语法(汉罗塔)

Java基础语法&#xff08;汉罗塔&#xff09; 1 起源2 需求3 分析3.1 1个碟子3.2 2个碟子3.3 3个碟子3.4 4个碟子3.5 规律 4 代码实现&#xff1a;直接算法5 代码实现封装&#xff1a;栈的思想 1 起源 汉罗塔&#xff08;又称河内塔&#xff09;问题是源于印度一个古老传说的益…

《经典递归问题:汉罗塔》

&#x1f320;作者&#xff1a;TheMythWS. &#x1f386;专栏&#xff1a;《JavaSE》 &#x1f387;座右铭&#xff1a;不走心的努力都是在敷衍自己&#xff0c;让自己所做的选择&#xff0c;熠熠发光。 目录 ✨汉罗塔的介绍 图解游戏​ ✨N层汉罗塔需移动的次数 ✨汉罗塔的…

数据链路层 功能概述

数据链路层的研究思想 数据链路层基本概念 数据链路层功能概述 数据链路层功能概述

数据链路层功能概述、封装成帧与透明传输

你一定要做自己&#xff0c;做自己喜欢的事&#xff0c;然后把自己交给命运 文章目录 本章启航思维导图数据链路层数据链路层基本概念数据链路层功能概述封装成帧透明传输组帧的四种方法字符计数法字符填充法零比特填充法违规编码法 本章启航思维导图 数据链路层 数据链路层基…

【计算机网络】数据链路层——数据链路层功能/组帧/差错控制

文章目录 数据链路层数据链路层的功能为网络层提供服务链路管理帧定界、帧同步与透明传输流量控制 组帧字符计数法字符填充的首尾定界符法零比特填充的首尾标志法违规编码法 差错控制检错编码奇偶校验码循环冗余码 纠错编码 数据链路层 数据链路层的功能 数据链路层在物理层提…

19数据链路层的功能

1、数据链路层的功能 数据链路层在物理层提供服务的基础上向网络层提供服务&#xff0c;其主要作用是加强物理层传输原始比特流的功能&#xff0c;将物理层提供的可能出错的物理连接改造成逻辑上无差错的数据链路&#xff0c;使之对网络层表现为一条无差错的链路。 2、为网络层…

计算机网络——数据链路层功能概述、封装成帧、差错控制、流量控制与可靠传输机制

文章目录 前言一、数据链路层功能概述二、封装成帧1、透明传输2、封装成帧3、组帧的方法⑴字符计数法⑵字符/节填充法⑶零比特填充法⑷违规编码法 三、差错控制1、差错由来2、检错编码⑴奇偶校验码⑵循环冗余码 3、纠错编码——海明码 四、流量控制与可靠传输机制1、停止等待协…

计算机网络【数据链路层的功能】

计算机网络【数据链路层的功能】 数据链路层基本概念数据链路层功能概述封装成帧透明传输字符计数法字符填充法零比特填充法 差错控制差错从何而来&#xff1f;CRC 循环冗余码 数据链路层基本概念 数据链路层使用的信道主要有一下两种类型&#xff1a; 点对点信道&#xff1a…

数据链路层主要功能

透明传输 个人理解&#xff0c;透明传输其实就是指无论是什么报文都可以传输&#xff0c;非透明传输就是指某些特殊字符不能传输&#xff0c;在计算机网络中&#xff0c;透明传输在数据链路层提到过&#xff0c;在数据链路层将网络层协议封装成帧时&#xff0c;会在首部和尾部分…

数据链路层(内容超多哦)

数据链路层——交换机 1. 数据链路概述2. 以太网2.1 以太网帧格式2.2 交换机设备简介2.3 交换机的工作原理2.4 交换机以太网的工作模式2.5 配置前的准备 3. 命令行的使用 1. 数据链路概述 数据链路层的功能&#xff1a;1.数据链路的建立、维护与拆除 2.帧包装、帧传输、帧同步…

计算机网络:数据链路层功能

文章目录 1.为网络层提供服务2.链路管理3.帧定界、帧同步与透明传输4.流量控制5.差错控制 数据链路层在物理层提供服务的基础上向网络层提供服务&#xff0c;其主要作用是加强物理层传输原始比特流的功能&#xff0c;将物理层提供的可能出错的物理连接改造为逻辑上无差错的数据…

计算机网络-数据链路层功能概述

数据链路层的研究思想 基本概念 结点: 主机, 路由器 链路: 网络中两个结点之间的物理通道, 链路的传输介质主要有双绞线, 光纤 和微波, 分为有线链路和无线链路 数据链路: 网络中两个结点的逻辑通道, 把现实控制数据传输协议的硬件和软件加到链路上就构成了数据链路 帧: 链…