问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

汉诺塔递归问题

发布网友 发布时间:2022-05-20 19:40

我来回答

4个回答

热心网友 时间:2023-11-07 10:53

#include <fstream>
#include <iostream>
using namespace std;
ofstream fout("out.txt");
void Move(int n,char x,char y)
{
fout<<"把"<<n<<"号从"<<x<<"挪动到"<<y<<endl;
}

void Hannoi(int n,char a,char b,char c)
{
if(n==1)
Move(1,a,c);
else
{
Hannoi(n-1,a,c,b);
Move(n,a,c);
Hannoi(n-1,b,a,c);
}
}
int main()
{
fout<<"以下是7层汉诺塔的解法:"<<endl;
Hannoi(7,'a','b','c'); //调用
fout.close();
cout<<"输出完毕!"<<endl;
return 0;

汉诺塔使用递归的方法来实现的
可能你对递归还没理解透,反正记住,程序总是一步一步的按顺序执行,有调用函数就先在调用的地方设个断点,转入函数执行,执行完了又返回断点,万变不离其宗!

程序执行的顺序
Hannoi(7,'a','b','c');这里调用函数,转入函数执行并传入参数n=7

第一步,执行判断语句,根据n的值进入else执行
第二步,执行Hannoi(n-1,a,c,b);这时是调用函数本身,也就是所谓的递归了,你看传入的值n-1,相当于传入n=6,还有a,c,b,的值,这个要注意顺序,在调用的时候a,c,b的值是第一次传入的值
第三步,执行Hannoi(int n,char a,char b,char c)函数,这点能理解吧,这次传入的值n=6了,但是a,b,c,的值相对于第一次的值有改变了哦,可以理解成,a(2)=a(1),b(2)=c(1),c(2)=b(1),这里括号里代表函数调用的次数,其实这里最容易弄混的就是,a,b,c的值,自己用本子把每次传入的值的a,b,c按传入顺序列出来,会容易理解些
同样,执行判断,n>1进入else,按顺序执行,先执行Hannoi(n-1,a,c,b);然后又是调用本身,注意传入的值,是a(2),c(2),b(2),又转入去执行Hannoi(int n,char a,char b,char c)函数,这时接收的值a(3)=a(2),b(3)=c(2),c(3)=b(2),就像在兜圈子是吧,没错。后面你自己做张表来理一下。
这样兜圈子直到n=1。你看Hannoi(n-1,a,c,b);每次n都是减了1的,所以n-1次递归的时候,就直接执行if(n==1)里面的了,终于有所改变了是吧,他执行的是Move(1,a,c); 也就是输出函数,执行完Move(int n,char x,char y) 返回原来的调用的那个断点。继续向后。没有语句了,就返回上次调用的函数,上次调用Hannoi(int n,char a,char b,char c)是谁呢,就是n-2次的Hannoi(int n,char a,char b,char c)中的Hannoi(n-1,a,c,b);调用的他啊,返回到这里,继续向后又遇到Move(n,a,c); 这里不用讲解了吧,输出后返回来,继续向后执行Hannoi(n-1,b,a,c); 新的递归开始了,看你再列个新的表理一下呢,注意传入的值和他的顺序,还有n的值这时是多少。

其实我的讲解你可能看的也不是很清楚,关键是要理解到递归他无非就是调用自己,调用完返回就是返回上次调用的地方,也是他自己,只是俩次的函数使用中的值是不一样的,这个值呢,最好拿笔记下来,并写个次数才容易理解和分析。

这递归程序很经典,值得研究,你会发现他是如此的巧妙,太棒了!建议测试的时候不要把n设的太大,不然容易死机!想想里面的循环次数就真令人咂舌了!

参考资料:原创

热心网友 时间:2023-11-07 10:54

汉诺塔的递归算法与解析

从左到右 A B C 柱 大盘子在下, 小盘子在上, 借助B柱将所有盘子从A柱移动到C柱, 期间只有一个原则: 大盘子只能在小盘子的下面.
如果有3个盘子, 大中小号, 越小的越在上面, 从上面给盘子按顺序编号 1(小),2(中),3(大), 后面的原理解析引用这里的编号.

递归算法简单来说就是方法内部自己调用自己, 同时也一定有一个结束点. 如果对方法调用栈了解的话,其实是很容易理解方法的调用过程的, 就是从主线程开始调用方法进行不停的压栈和出栈操作. 方法的调入就是将方法压入栈中, 方法的结束就是方法出栈的过程, 这样保证了方法调用的顺序流. 如果跟踪递归的调用情况会发现也是如此, 到最后一定是这个方法最后从栈中弹出回到主线程, 并且结束.
栈的特点:先进后出。 比如一个方法 A 自己调用自己, 我用编号区分一下进栈过程:
A -> A(1) -> A(2) -> A(3)
在A(3)时满足某种条件得以退出, 回到 A(2), A(2)结束回到A(1), 再回到A, 出栈过程:
A(3) -> A(2) -> A(1) -> A
对于递归,还有一个形象的认识,就是我小时候家里有一个柜子, 柜子两端都是玻璃, 头伸进柜子看一面镜子,会看到镜子里还有镜子, 然后镜子里还有镜子, 但和递归的特点不同的是这镜子的反射是没有尽头的, 只要眼睛一直能看到底的话.
了解完递归后, 再回头来看如何用递归的方式解决汉诺塔的问题.
案例 1 - 假设只有一个盘子的时候, 盘子数量 N=1
只有一个步骤 将第1个盘子从A移动到C, 为了对比方便我这样来描述这个步骤:
步骤 盘子编号 从柱子移动 移动到柱子
1 1 A C
案例 2 - 如果有两个盘子, 盘子数量 N = 2
步骤 盘子编号 从柱子移动 移动到柱子
1 1 A B
2 2 A C
3 1 B C
案例 3 - 如果有三个盘子, 盘子数量 N = 3
步骤 盘子编号 从柱子移动 移动到柱子
1 1    A C
2 2    A     B
3 1 C B
4 3 A C
5 1 B A
6 2 B C
7 1 A C
如何找出盘子移动的规律 ?
我们要做的最重要的一件事情就是永远要把最底下的一个盘子从 A 移动到 C
看看上面从1个盘子的移动到3个盘子的移动, 在移动记录中,当盘子的编号和盘子数量相同的时候他们的步骤都是从A移动到C (看加粗的部分),其它的步骤对等.
再观察第3个案例中的第 1-3 步 和 第 5-7步
第 1-3 步 目的是从 A 移动到 B 如果我们把 B 当作终点, 那么这里的第 1-3 步理解起来和 第2个案例的三个步骤完全相同, 都是通过一个柱子来移动,和第2个案例比起来在后面加括号来表示
1 1    A C ( A -> B)
2 2    A  B ( A -> C)
3 1 C B ( B -> C)
总结:将盘子B变成C即可.
第 5-7 步 目的是从 B 移动到 C 如果我们把 C 当作终点, 那么这里的 5-7 步理解起来和上面也是一样的, 和第2个案例的三个步骤也完全相同.和第2个案例比起来就是:
5 1 B A ( A -> B)
6 2 B C ( A- > C)
7 1 A C ( B -> C)
总结: 将盘子B变成A即可
根据这个演示可以明确几点规律:
1. 当盘子只有一个的时候,只有一个动作 从 A 移动到 C 即结束.
2. 当有N个盘子的时候, 中间的动作都是从 A 移动到 C, 那么表示最下面的第N个盘子移动完毕
3. 中间动作之上都可以认为是: 从 A 移动到 B
4. 中间动作之下都可以认为是: 从 B 移动到 C
2,3,4 可以表示为
1 1 A B
2 2 A C
3 1 B C
这种结构一直在重复进行,C#不太熟悉,试着写写,就有了以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DataStructure
{
class HanoiTower
{

public void MoveDisk(int DiskQuantity,string PositionA, string PositionB, string PositionC)
{
// If there's only one disk, then end.
if (DiskQuantity == 1)
{
Console.WriteLine("Move disk from position {0} to {1}.", PositionA, PositionC);
// Must return
return;
}
else
{
// Step 1 - Change B to C (A --> B)
MoveDisk(DiskQuantity - 1, PositionA,PositionC,PositionB);
// Step 2 - No changes (A --> C)
MoveDisk(1, PositionA, PositionB, PositionC);
// Step 3 - Change B to A (A --> C)
MoveDisk(DiskQuantity - 1, PositionB, PositionA, PositionC);
}
}

static void Main(string[] args)
{
HanoiTower hanoi = new HanoiTower();

Console.WriteLine("Please input Disk Quantity:");
int DiskQuantity = Convert.ToInt32(Console.ReadLine());

hanoi.MoveDisk(DiskQuantity, "A", "B", "C");

Console.ReadKey();
}
}
}

结合上面的分析,最重要的就是这里的3步交换动作, 中间从 A到C的动作是最底层盘子的最终操作.
//Step 1 - Change B to C (A --> B)
MoveDisk(DiskQuantity - 1, PositionA,PositionC,PositionB);
//Step 2 - No changes (A --> C)
MoveDisk(1, PositionA, PositionB, PositionC);
//Step 3 - Change B to A (A --> C)
MoveDisk(DiskQuantity - 1, PositionB, PositionA, PositionC);
至于第1个参数为什么是DiskQuantity - 1,或者1 大家再回到上面看看是不是所有的步骤都是.. 1. 1,2,1. 1,2,1,3,1,2,1 这种以盘子数对称的结构,而它前后都是重复1,2,1 的过程.

热心网友 时间:2023-11-07 10:55

递归就是调用自己,可以把递归看成一模一样的楼层
如果是三个盘,看成三层楼
编号1,2,3
n=3时,执行else,Hannoi(n-1,a,c,b);在这时调用自己,进入递归第二层 ,再执行else,Hannoi(n-1,a,c,b);这时调用自己,进入第三层,这时因为n=1,所以程序执行if,if(n==1) Move(1,a,c);编号1移动后,跳出递归第三层,回到第二层,这就意味着n=2在 Hannoi(n-1,a,c,b);这一步执行完毕,往下执行Move(n,a,c);移动后,执行Hannoi(n-1,b,a,c);接着调用n=1时,完成后第二层执行完成,跳出,执行n=3第一层的move,这样一直循环调用,直到move被执行2的n次方减1次,完成移动。

热心网友 时间:2023-11-07 10:55

PROGRAM ex9;
VAR n,m:integer;
FUNCTION hanoi(n:integer;x,y,z:char):integer;
BEGIN
IF n=1 THEN
begin hanoi:=1;write(x,'->',z,' ') end
ELSE hanoi:=hanoi(n-1,x,z,y)+hanoi(1,x,y,z)+hanoi(n-1,y,x,z);
END;
BEGIN
write('n = ');read(n);
m:=hanoi(n,'A','B','C');
writeln(chr(13),chr(10),'hanoi(',n,')=',m)
END.
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
飞行员多久能考 自费飞行员学历有什么要求 考民航飞行员是公费自费 民航飞行员报考是自费吗 路虎pin码是多少 发财树的寓意和象征 ...发财树有什么寓意?养发财树需要注意什么?_百度... 成年男子标枪重量 标枪运动用的标枪重量是多少? 成年组比赛中男女标枪的重量分别是 谁有汉诺塔游戏(带动画)c语言源代码(? 汉诺塔c语言 动画演示 地址1162765886@qq.com 如何用matlab实现汉诺塔的动画过程? 在北京开工作室怎么去注册啊,需要多少钱,都交什么费 动态演示汉诺塔算法的实现过程 求汉诺塔c语言动画演示程序 8寸的蛋糕大约要多少钱? 急!Hanoi塔问题的动画演示 我想在北京注册办理个人工作室,个体公司的执照多少钱。 C#汉诺塔动画 手帐的工具在哪买?(新台子的) 安旗蛋糕8英寸多少钱 金字旁上面白下面木什么字 哪个看码高手帮我看看这 正品耐克 詹姆斯11代兵马俑篮球鞋 10代男子LEBRON XI LBJ1 现在的英国首相是谁? 英国第一届首相是谁 英国的历任首相都是谁? 詹姆斯十代和詹姆斯十一代哪个适合打水泥地,去香港买詹姆斯十代的话,大概多少港币,十一代呢? 女人最嫩最水灵的是不是18岁 上届英国首相是谁 用计算机画图要怎么样从最基础的一步步学起? 拇外翻怎样手术治疗 拇外翻的治疗方式有哪些,手术后可能面对什么风险,需要注意什么问题? 拇外翻的治疗方法有哪些? 法拍房有房本可以公积金贷款吗? 买的有房本的旧房能用住房公积金贷款吗?手续复杂吗? 治疗拇外翻比较好方法有什么? 拇外翻整形手术的特点有哪些呢 我想用房本一次性贷款住房公积金! 竹笋怎么剥剥到什么程度 毛竹笋怎么剥视频 中国“天问一号”即将飞往火星,这对我国航天会带来怎样的影响? 灵芝和什么搭配泡水喝治咳嗽 第一个环绕火星的太空船叫什么? 想注销支付宝账号,显示当前账号存在争议,无法注销,是什么情况?存在争议是包括哪方面? 求一本小说男主是陈凡 求一本主角叫陈凡的小说 女主雪儿 主角兄弟黑狗,陈凡,那部小说,主角记不住了,小时候主角和女主是青梅竹马? 蒙华4号食用向日葵种子多少钱一斤 初一英语听力视频