| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2808 人关注过本帖
标题:请教汉诺塔递归问题
只看楼主 加入收藏
kikokokoo
Rank: 2
等 级:论坛游民
帖 子:21
专家分:29
注 册:2011-8-6
结帖率:100%
收藏
已结贴  问题点数:0 回复次数:7 
请教汉诺塔递归问题
move(int n,int a,int b,int c)
{
    if(n==1)
        printf("%c-->%c\n",a,c);
    else
    {
        move(n-1,a,c,b);  /*n=1,a=A,b=C,c=B*/
        printf("%c-->%c\n",a,c);
        move(n-1,b,a,c);  /*n=1,a=B,b=A,c=C*/
    }
}

main()
{
    int h;
    printf("\ninput number:\n");
    scanf("%d",&h);
    printf("the step to moving %d disks:\n",h);
    move(h,'A','B','C');
    getch();


自定义函数部分比较难理解,是不是进栈和出栈的问题。
特别是  move(n-1,a,c,b);  /*n=1,a=A,b=C,c=B*/
        printf("%c-->%c\n",a,c);
假设n=2(就是A柱上只有两个盘子),是不是先执行move(1,a,c,b),printf....然后执行move(2,a,c,b),printf......。这两步执行完后在执行下面那步move(n-1,b,a,c)。
搜索更多相关主题的帖子: number moving 
2011-08-28 09:21
laoyang103
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:内蒙古包头
等 级:贵宾
威 望:19
帖 子:3082
专家分:11056
注 册:2010-5-22
收藏
得分:10 
楼主不要用栈区理解 用树去理解 其实每一个递归都会有一颗递归调用树 现在就拿汉诺塔递归来举例说明:
move(int n,int a,int b,int c)//参数可以先不用看
{
    if(n==1)//这个是递归的出口 不用解释了吧
        printf("%c-->%c\n",a,c);
    else
    {
        move(n-1,a,c,b); //将上面的n-1个盘子借助C移动到B
        printf("%c-->%c\n",a,c);//将最底下的一个盘子移动到C
        move(n-1,b,a,c);  //讲B上面的n-1个盘子借助A移动到B上
    }
}
这个就是汉诺塔的递归思路 那么它的递归调用树是啥样的? 我们可以看看他的递归函数体内调用了几次自身

可以看到这个函数除了到达出口会返回   其他情况都是无条件的调用自身两次 所以它的递归调用树是一颗满二叉树

那么你也就知道为啥n层汉诺塔需要2^n - 1 次才能完成  因为深度为n的满二叉树它的结点个数为2^n - 1个

相关的你可以看看求全排列的递归调用树 为什么它的调用树的叶子结点个数为n!个


                                         
===========深入<----------------->浅出============
2011-08-28 10:01
lz1091914999
Rank: 14Rank: 14Rank: 14Rank: 14
来 自:四川
等 级:贵宾
威 望:37
帖 子:2011
专家分:5959
注 册:2010-11-1
收藏
得分:10 
move(n-1,a,c,b)              把上面n-1个罗盘移动到b
printf("%c-->%c\n", a, c);   把a上剩下的一个罗盘移动到c
move(n - 1, b, a, c)         把b下的所有(n-1)个罗盘移动到c

My life is brilliant
2011-08-28 13:30
laoyang103
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:内蒙古包头
等 级:贵宾
威 望:19
帖 子:3082
专家分:11056
注 册:2010-5-22
收藏
得分:0 
回复 3楼 lz1091914999
还需要借助中间盘子

                                         
===========深入<----------------->浅出============
2011-08-28 15:22
云杨
Rank: 1
等 级:新手上路
帖 子:20
专家分:4
注 册:2011-10-25
收藏
得分:0 
Hanio问题可以分成三个步骤,两类操作:
(1)将A上n-1个盘借助C座先移到B座上;
(2)把A座上剩下的一个盘子移到C座上;
(3)将n-1个盘子下从B座借助A座移到C座;

两类操作:
(1)将n-1个盘子从一个座移到另一个座(n>1)。这就是大和尚让小和尚做的工作
    它是一个递归的过程,即和尚将任务层层下放,知道第64个和尚为止。
(2)将一个盘子从一个座移到另一个座上。这是大和尚自己的工作。

代码只有几行,但理解起来没有那么容易的,需要仔细揣摩的。
2011-11-01 12:57
云杨
Rank: 1
等 级:新手上路
帖 子:20
专家分:4
注 册:2011-10-25
收藏
得分:0 
正在理解的.
2011-11-01 12:58
Naturalstory
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2012-12-8
收藏
得分:0 
还是不理解
2012-12-08 20:32
whukeming
Rank: 2
等 级:论坛游民
帖 子:76
专家分:51
注 册:2008-8-24
收藏
得分:0 
刚接触递归,我也研究了好久,总算搞懂递归的执行步骤了,
仔细研究下下面的程序,应该能想明白了。
程序代码:
//
//  main.c
//  递归汉诺塔
//
//  Created by Hu Keming on 13-3-29.
//  Copyright (c) 2013年 Hu Keming. All rights reserved.
//

# include "stdio.h"
void move(char x, char y) //自定义move函数,用来将块从起始柱子x移动到目标柱子y,这里的x,y为形参,不代表具体哪根柱子

{
    printf("\t%c-->%c\n",x,y);
}
void hannuota(int n, char a, char b, char c) //自定义hannuota函数,这里的a,b,c为形参,不代表具体哪根柱子

{
    if (n == 1)
        move(a, c); //调用自定义函数move
                                                                       
    else                                                               
                                                                       
    {        
        hannuota(n-1, a, c, b);  //第一行递归
        
        move(a, c);  //调用自定义函数move
        
        hannuota(n-1, b, a, c);  //第二行递归
        
    }
}


int main(void)

{
    int n;
    
    printf("请输入要移动的块数:\n");
    scanf("%d", &n);
  
    hannuota(n, 'a', 'b', 'c');
    
    return 0;
}
/*执行详细步骤:当n = 3 时
                 n = 3           n = 2          n = 1
                
                |               |h(1, a, b, c)=>move(a, c)=> a->c      //1
                |h(2, a, c, b)    |move(a, b)                  a->b      //2
                |               |h(1, c, a, b)=>move(c, b)=> c->b      //3
                |

 h(3, a, b, c)    |move(a, c)                                  a->c      //4
                |
                |               |h(1, b, c, a)=>move(b, a)=> b->a      //5                      
                |h(2, b, a, c)    |move(b, c)                  b->c      //6
                |               |h(1, a, b, c)=>move(a, c)=> a->c      //7
                |


 执行结果:

 请输入要移动的块数:

 3

 a-->c

 a-->b

 c-->b

 a-->c

 b-->a

 b-->c

 a-->c

 */
2013-03-31 11:25
快速回复:请教汉诺塔递归问题
数据加载中...
 
   



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

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