| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1319 人关注过本帖
标题:汉诺塔 理解不了怎办???
取消只看楼主 加入收藏
々NARUTO
Rank: 2
等 级:论坛游民
帖 子:80
专家分:85
注 册:2011-6-19
结帖率:77.78%
收藏
已结贴  问题点数:20 回复次数:6 
汉诺塔 理解不了怎办???
#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
々NARUTO
Rank: 2
等 级:论坛游民
帖 子:80
专家分:85
注 册:2011-6-19
收藏
得分:0 
回复 2楼 笑傲
????????
我晓得 那样做 一定会 出正确结果的
只是 不晓得 如何从 他们所说的那种思维去理解 ..................

2013-05-01 10:36
々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
々NARUTO
Rank: 2
等 级:论坛游民
帖 子:80
专家分:85
注 册:2011-6-19
收藏
得分:0 
回复 7楼 邓士林
这个思想 我晓得.
肯定是要先将 最底层的最大的一个 肯定是要在n-1个之前 放到C上的  这是这个游戏的规则  大的不能再小的上面 .然后再将n-1放 C上 这些 我都晓得
看第5楼和前几楼  这个程序是按着那个思想写的  但,我怎么也理解不了 那程序的执行流程 是围绕和遵循着 那个思想....  我的疑惑是这个...
 
2013-05-02 15:18
々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
々NARUTO
Rank: 2
等 级:论坛游民
帖 子:80
专家分:85
注 册:2011-6-19
收藏
得分:0 
以下是引用helloUJS在2013-5-4 13:46:25的发言:

我个人觉得你对递归的理解有些偏差,如果要设计一个递归函数fun(n),只要能把fun(n)转换成fun(n-1)的问题,并且当n为特定值时(比如n=1)问题的答案是已知的,就可以了,而不必关心fun(n-1)是如何计算出来的,这正是递归的优势,因为如果搞清楚fun(n-1)的情况,那就直接用循环就可以了,因为递归需要更多的资源,速度也没有循环快,实际上一个问题只要能转换成一个分段函数的形式,使用递归实现是非常方便的。如下几个例子不知是否有助于理解递归:
1. s(n)=1+2+3+.....+n
             1     当n=1时
    s(n)=
             s(n-1)+n     当n>1时     不必关心s(n-1)如何计算出
对应的递归函数:
int S(int n)
{
   int sum;
   if(n==1)
       sum=1;
   else
       sum=S(n-1)+n;    /*不必关心如何计算出S(n-1)*/
  return sum;
}
2.  S(a,b)=f(x)在[a,b]上的定积分
假设运用矩形法计算,S(a,b)可以转换成如下分段函数:
              f(a)*(b-a)     当|a-b|足够小(比如小于1e-6)
   S(a,b)=
              S(a,(a+b)/2)+S((a+b)/2,b)    当|a-b|>1e-6时   不必关心S(a,(a+b)/2)和S((a+b)/2,b)如何计算出来
对应的递归函数是:
float S(float a,float b)
{
   float sum;
   if(fabs(a-b)<=1e-6)
      sum=f(a)*(b-a);   /*假设f(x)已经定义*/
   else
     sum=S(a,(a+b)/2)+S((a+b)/2,b); /*不必知道S(a,(a+b)/2)如何计算出来*/
   return sum;
}
3. bprint(n)=打印出十进制数n对应的二进制
                 打印n    当n<2时
   bprint(n)=   
                bprint(n/2)  当n>2时,先打印n/2对应的二进制,然后再打印n对应的二进制的最后1位(n%2)
                打印 n%2
对应的递归函数:
void bprint(int n)
{
   if(n<2)
     printf("%d",n);
   else
     {
       bprint(n/2);   /*不必关心如何打印出n/2对应的二进制*/
       printf("%d",n%2);
      }
}
非常感谢你整理的那些资料
------------------------------------------------------------------------------------------------------------------------------
其实 我的话 主要是被 伪代码 给糊涂了

我记得伪代码 当初 有句是这样写的
将f1借助f3移到f2
这样的话 搞得我当初 总是有一种 直线的思维 就是 f1是第一根柱子 f3是第三根柱子 f2是第二根柱子
                                          这样理解的话  就是所有的n-1,n-2,n-3...的盘子都从第一根借助第三根移到第二根
                                          搞得我对从程序源码的实现这些 都糊涂了好多 那程序思想明明和代码不符.   
所以刚开始 我说了这些话
                                         // 调用此函数说是为了借助f3从f1移到f2                                                  
                                         //可是这调用的实参和形参都是颠倒的,也就是说第一次调用是移到了f2但是,第二次由于形参和
                                         //实参的颠倒  ,表面上看去是已到了f2实际上是移到了f3.
还说了 什么程序如何 遵循那个思想的...............

还是到后面 才怀疑起来 那样的话可以直接写个hanuota('a','c','b')而无需hannuota(f1,f3,f2),f3真的只代表的是第三根柱子吗
主要就是在这里一点 才豁然开朗.
--------------------------------------------------------------------------------------------------------------------------------
The End,Thank U Very Much...                                                                                            2013.5.4
--------------------------------------------------------------------------------------------------------------------------------
2013-05-04 19:03
快速回复:汉诺塔 理解不了怎办???
数据加载中...
 
   



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

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