| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1319 人关注过本帖
标题:汉诺塔 理解不了怎办???
只看楼主 加入收藏
々NARUTO
Rank: 2
等 级:论坛游民
帖 子:80
专家分:85
注 册:2011-6-19
结帖率:77.78%
收藏
已结贴  问题点数:20 回复次数:11 
汉诺塔 理解不了怎办???
#include<stdio.h>
void hannuota(int n,char f1,char f2,char f3);
int main()
{
    int n;
    printf("请输入盘子的个数:");
    scanf("%d",&n);
    hannuota(n,'A','B','C');
    return 0;
}
void hannuota(int n,char f1,char f2,char f3)
{
    if (1==n)                                          //他这明明 是将最上层的一个 盘子移过去,为何 却说是,最后只剩下一的个,移过去
    {
        printf("编号%d 从%c移动到%c\n",n,f1,f3);                  
    }
    else
    {
        hannuota(n-1,f1,f3,f2);                     //调用此函数说是为了借助f3从f1移到f2                                                  
                                                    //可是这调用的实参和形参都是颠倒的,也就是说第一次调用是移到了f2但是,第二次由于形参和
                                                    //实参的颠倒  ,表面上看去是已到了f2实际上是移到了f3.
        printf("编号%d 从%c移动到%c\n",n,f1,f3);
        hannuota(n-1,f2,f1,f3);                             
    }
    return;
}
//反正 光从 伪代码 去理解 源代码  不晓得为何 很难理解,,,很糊涂
搜索更多相关主题的帖子: include return 
2013-05-01 07:49
笑傲
Rank: 8Rank: 8
来 自:迪拜
等 级:蝙蝠侠
威 望:5
帖 子:223
专家分:856
注 册:2013-3-9
收藏
得分:5 
拿个实例跟踪一下程序就知道了

练就一身本领,只为笑傲江湖!
2013-05-01 09:44
々NARUTO
Rank: 2
等 级:论坛游民
帖 子:80
专家分:85
注 册:2011-6-19
收藏
得分:0 
回复 2楼 笑傲
????????
我晓得 那样做 一定会 出正确结果的
只是 不晓得 如何从 他们所说的那种思维去理解 ..................

2013-05-01 10:36
笑傲
Rank: 8Rank: 8
来 自:迪拜
等 级:蝙蝠侠
威 望:5
帖 子:223
专家分:856
注 册:2013-3-9
收藏
得分:5 
hannuota( n,f1, f2, f3)说明将n个盘子以f2为中介,从f1移到f3上,但要达到这个效果就要先把顶上n-1个盘子从f1移到f2上(此时就需要以f3作为中介了),再把最后一个盘子从f1移到f3上,然后再将f2上的n-1个盘子移到f3上即可(将f2上的盘子移到f3上就要以f1为中介),如此递归即可;就是数学上的逆推的思想;
从上面的分析可以看出来最后会分析到n==1的情况;当n==1的时候就不需要中介了,直接移过去就好了;

练就一身本领,只为笑傲江湖!
2013-05-01 13:13
々NARUTO
Rank: 2
等 级:论坛游民
帖 子:80
专家分:85
注 册:2011-6-19
收藏
得分:0 
首先 先谢谢你.

递归 这些什么的 我都理解 只是不晓得 程序的执行如何围绕了那个神马n-1放B上 n放C上 然后n-1借助A放C上     的思想

程序代码:
例如 要移动3个盘子

先调用 hannuota(3,’A’,’B’,’C’)
因为 n!=1 所以 又调用 hannuota(2,’A’,’C’,’B’)
因为 n!=1 所以 调用 hannuota(1,A’,’B,’C)
此时 因为n==1
所以
输出语句编号1从A移动到C
然后返回 

返回到hannuota(2,’A’,’C’,’B’)
接着执行后面的语句
输出语句编号2从A移动到B
然后 调用hannuota(1,’C’,’A,’B’)
因为n==1
所以
输出语句编号1从C移动到B
然后 返回返回

返回到hannuota(3,’A’,’B’,’C’)
输出语句编号3从A移动到C
然后调用hannuota(2,’B’,’A,’C’)
因为n!=1 所以 调用hannuota(1,’B’,’C,’A’)
因为n==1 所以 输出编号1从B移动到A
然后返回

返回到hannuota(2,’B’,’A,’C’)
输出语句编号2从B移动到C
然后 调用hannuota(1,’A’,’B’,’C’)
因为n==1所以 输出编号1从A移动到C

然后返回返回 结束



2013-05-02 14:39
々NARUTO
Rank: 2
等 级:论坛游民
帖 子:80
专家分:85
注 册:2011-6-19
收藏
得分:0 
求解决 我心中的疑惑
2013-05-02 14:40
邓士林
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:淮河河畔
等 级:贵宾
威 望:61
帖 子:2392
专家分:13384
注 册:2013-3-3
收藏
得分:5 
void hannuota(int n,char f1,char f2,char f3)
{
    if (1==n)                                          //移动思想就是将A上的借助C,移动到B,然后在将B上的借助A,移动到C,这样就成功了,    {
        printf("编号%d 从%c移动到%c\n",n,f1,f3);                  
    }
    else
    {
        hannuota(n-1,f1,f3,f2);                     //调用此函数说是为了借助f3从f1移到f2                                                  
                                                    //可是这调用的实参和形参都是颠倒的,也就是说第一次调用是移到了f2但是,第二次由于形参和
                                                    //实参的颠倒  ,表面上看去是已到了f2实际上是移到了f3.
        printf("编号%d 从%c移动到%c\n",n,f1,f3);
        hannuota(n-1,f2,f1,f3);                             
    }
    return;
}
参数没什么关系,只要位置对就行,比如有n个盘子,可以分为n-1和一个,一个最大的在下面,n-1个在上面,看成个整体,你为了移动成功,是不是必须先把最后一个先放到正确的位置,这也就是为什么是最后一个了。然后就递归

Maybe
2013-05-02 14:53
々NARUTO
Rank: 2
等 级:论坛游民
帖 子:80
专家分:85
注 册:2011-6-19
收藏
得分:0 
回复 7楼 邓士林
这个思想 我晓得.
肯定是要先将 最底层的最大的一个 肯定是要在n-1个之前 放到C上的  这是这个游戏的规则  大的不能再小的上面 .然后再将n-1放 C上 这些 我都晓得
看第5楼和前几楼  这个程序是按着那个思想写的  但,我怎么也理解不了 那程序的执行流程 是围绕和遵循着 那个思想....  我的疑惑是这个...
 
2013-05-02 15:18
helloUJS
Rank: 8Rank: 8
等 级:蝙蝠侠
帖 子:168
专家分:731
注 册:2013-3-27
收藏
得分:5 
看看这个能不能帮助理解,每行最后的数字就是移动盘子的次序。
'                                                          (1)-1 Hanoi(1,’a’,’b’,’c’)=move(‘a’,’c’)---1
                            (1) Hanoi(2,’a’,’c’,’b’)=(1)-2 move(‘a’,’b’)------------------------------2
                                                           (1)-3 Hanoi(1,’c’,’a’,’b’) =move(‘c’,’b’)--3
Hanoi(3,’a’,’b’,’c’)= (2) move(‘a’,’c’)---------------------------------------------------------------4      
                                                           (3)-1 Hanoi(1,’b’,’c’,’a’)=move(‘b’,’a’)---5
                            (3) Hanoi(2,’b’,’a’,’c’)=(3)-2 move(‘b’,c’)--------------------------------6
                                                           (3)-3 Hanoi(1,’a’,’b’,’c’)=move(‘a’,’c’)---7
2013-05-04 08:45
々NARUTO
Rank: 2
等 级:论坛游民
帖 子:80
专家分:85
注 册:2011-6-19
收藏
得分:0 
回复 9楼 helloUJS
其实递归的整个 执行流程 我都晓得...  我在第5楼的 时候 就把整个递归流程 全部叙述了.
我觉得话呢 好多人 还是没真正的回答到 真正的疑惑  例如  f2不一定就是第二根(b)柱子的 只是放了盘子的柱子.

这些不解决的话,  如果 光从 伪代码 去看的话 好难想 !!!!很容易会成一种 直线的思维......

最后的话呢,自己反复挣扎了 ,终于可以把代码和思想相理解的解释了
希望 跟我一样遇到此问题的人 有个帮助.............
void hannuota(int n,char f1,char f2,char f3)
{
    if (1==n)                    // 其实 这里相当于一个发动点 表示 将第1个 到第 n个和n前面的盘子开始依次移动   
   {
        printf("编号%d 从%c移动到%c\n",n,f1,f3);                  
    }
    else
    {
        hannuota(n-1,f1,f3,f2);//这里的话 这种颠倒的使得符合游戏规则 可以 怎么说呢 ,例:n-1个 需要先将n-2个放B上 然后因为这种的参数颠倒可以使n-2放在n-1个上 可以依次类推      
        printf("编号%d 从%c移动到%c\n",n,f1,f3); //将第n前面的直接放在不一定是c上的位置,就如我前面所说的颠倒性.但第n个绝对是c的因为刚开始调用就指定了的
        hannuota(n-1,f2,f1,f3); //然后这里的f2其实是就是 放了盘子的柱子上 不一定是b的(只是表示着 放了n-1盘子的柱子上) 移到c上                        
    }
    return;
}

2013-05-04 11:15
快速回复:汉诺塔 理解不了怎办???
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.049162 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved