A. 汉诺塔流程图
你好!
汉诺塔流程图:
voidmove(int,char,char,char);/*声明函数,告诉系统我随后要定义一个函数,他不对其中参数进行检查,所以可以省略参数,一般只写类型,表示有多少个什么类型的参数,便于自己理解*/
main()
{intn;
printf("请输入盘数n=");
scanf("%d",&n);
printf("在3根柱子上移%d只盘的步骤为: ",n);
move(n,'a','b','c');}/*函数调用,用a,b,c代表3跟柱子,把盘子数,柱子代码传给函数*/
voidmove(intm,charp,charq,charr)//定义函数
{if(m==1)
{printf("[%d]move1#from%cto%c ",step,p,r);
step=step+1;}
else{move(m-1,p,r,q);//调用本身函数,进行递归A
printf("[%d]move%d#from%cto%c ",step,m,p,r);
step=step+1;
move(m-1,q,p,r);//再次调用B
}
getch();}
递归其实是嵌套调用,
所谓嵌套调用,就是在一个函数里调用另一个函数,
main函数不能被调用的,
所以递归就是有限次的嵌套调用本身函数
每次调用,系统都会重新分配内存,
返回时就返回上次调用他的那块内存中的调用函数处,
这样理解应该很简单了
汉诺塔流程图解析:
这里面的递归涉及一个汉诺塔的算法问题,具体讲明白的话有点麻烦,总体思路是假设盘子全在a柱上,想放到c上
第N个人就想要是有人搬动其他N-1个盘子到b,那他只要搬一次从a到c就可以,在让那个人把N-1个盘子放到c上
第N-1那个人就想要是有人搬动其他N-2个盘子到c,他只要搬动一次从a到b就可以,在让那个人把N-2个盘子放到b上
....
第1个人就直接把盘子从a到c
这样形成递归
我在俩处调用标记了A,B,我写出步踌,你看看.
假设3个盘子
A函数相当于双重循环中的外层循环
B函数相当于双重循环中的内层循环
1,主函数调用,p=a,q=b,r=c,m=3,运行A,调用本身(A第一次调用)传入p,r,q(a,c,b)注意调用函数中p,r,q排列
2,被调函数是用p,q,r的顺序接收传入的p,r,q.p=a,q=c,r=b,m=2,执行A,调用本身(A第二次调用)调用传入p,r,q(a,b,c)
3,p=a,q=b,r=c,m=1,执行if,输出a->c,返回A第二次调用
4,本次函数中p=a,q=c,r=b,m=2,向下执行,输出a->b,执行B,调用本身(B第一次调用),传入q,p,r(c,a,b),m=1
5,p=c,q=a,r=b,m=1,执行if,输出c->b,返回B第一次调用
6,向下执行,执行完毕,返回A第一次调用
7,本次函数中p=a,q=b,r=c,m=3,向下执行,输出a->c,执行B,调用本身(B第一次调用),传入q,p,r(b,a,c),m=2
8,p=b,q=a,r=c,m=2,执行A,调用本身(A'第一次调用,注意是B函数调用中再次调用A)传入p,r,q(b,c,a)
9,p=b,q=c,r=a,m=1,执行if,输出b->a,返回A'第一次调用
10,本次函数中p=b,q=a,r=c,m=2向下执行,输出b->c,执行B,调用本身(B'的第一次调用,注意是B函数中再次调用B)传入q,p,r(a,b,c),m=1
11,p=a,q=b,r=c,m=1,执行if,输出a->c返回B'第一次调用
12,向下执行,执行完毕,返回B第一次调用
13,向下执行,执行完毕,返回主函数
仔细分析每次调用时当前变量p,q,r中所代表的a,b,c,每次调用时,p,q,r都是新的变量
我看了你的问题,估计你把调用函数中的p,q,r变量与被调函数中p,q,r变量搞混了
/*
4,向下执行,执行B,调用本身(B第一次调用),由于本次函数中p=a,q=c,r=b,m=2,先输出a->b,再传入q=c,p=a,r=b,m=1
这里不是[4]move3#fromatoc吗
*/
注意调用传入的顺序是q,p,r,传入的值是c,a,b的顺序,被调函数中是拿p,q,r的顺序在接收,所以被调函数中值的顺序就该是p=c,q=a,r=b,执行if就输出c->b
补充:流程图步骤画了好久额,有什么疑问发我邮箱[email protected]
B. 汉诺塔该怎么玩,方法
汉诺塔算法介绍:
一位美国学者发现的特别简单的方法:只要轮流用两次如下方法就可以了。
把三根柱子按顺序排成“品”字型,把所有圆盘按从大到小的顺序放于柱子A上,根据圆盘数量来确定柱子排放的顺序:
n若为偶数的话,顺时针方向依次摆放为:ABC;而n若为奇数的话,就按顺时针方向依次摆放为:ACB。这样经过反复多次的测试,最后就可以按照规定完成汉诺塔的移动。
因此很简单的,结果就是按照移动规则向一个方向移动金片:
如3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C。
(2)汉诺塔算法的流程图扩展阅读:
汉诺塔经典题目:
三根相邻的柱子,标号为A,B,C,A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘,要把所有盘子一个一个移动到柱子B上,且每次移动同一根柱子上都不可以出现大盘子在小盘子上方的情况。
至少需要几次移动的问题,我们设移动次数为H(n)。
把上面n-1个盘子移动到柱子C上,把最大的一块放在B上,把C上的所有盘子移动到B上,由此我们得出表达式:
H⑴ = 1
H(n) = 2*H(n-1)+1 (n>1)
很快我们就可以得到H(n)的一般式为:
H(n) = 2^n - 1 (n>0)
且这种方法的确是最少次数的,证明非常简单,可以尝试从2个盘子的移动开始证,可以试试。
进一步加深问题:
假如现在每种大小的盘子都有两个,并且是相邻的,设盘子个数为2n,问:⑴假如不考虑相同大小盘子的上下要几次移动,设移动次数为J(n);⑵只要保证到最后B上的相同大小盘子顺序与A上时相同,需要几次移动,设移动次数为K(n)。
⑴中的移动相当于是把前一个问题中的每个盘子多移动一次,也就是:
J(n) = 2*H(n) = 2*(2^n - 1) = 2^(n+1)-2
在分析⑵之前,我们来说明一个现象,假如A柱子上有两个大小相同的盘子,上面一个是黑色的,下面一个是白色的,我们把两个盘子移动到B上,需要两次。
盘子顺序将变成黑的在下,白的在上,然后再把B上的盘子移动到C上,需要两次,盘子顺序将与A上时相同,由此我们归纳出当相邻两个盘子都移动偶数次时,盘子顺序将不变,否则上下颠倒。
回到最开始的问题,n个盘子移动,上方的n-1个盘子总移动次数为2*H(n-1),所以上方n-1个盘子的移动次数必定为偶数次,最后一个盘子移动次数为1次。
讨论问题⑵:
综上可以得出,要把A上2n个盘子移动到B上,可以得出上方的2n-2个盘子必定移动偶数次,所以顺序不变,移动次数为:
J(n-1) = 2^n-2
然后再移动倒数第二个盘子,移动次数为2*J(n-1)+1 = 2^(n+1)-3,
最后移动最底下一个盘子,所以总的移动次数为:
K(n) = 2*(2*J(n-1)+1)+1 = 2*(2^(n+1)-3)+1 = 2^(n+2)-5
C. 汉诺塔问题
汉诺塔(又称河内塔)问题是印度的一个古老的传说。开天辟地的神勃拉玛在一个庙里留下了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,庙里的众僧不倦地把它们一个个地从这根棒搬到另一根棒上,规定可利用中间的一根棒作为帮助,但每次只能搬一个,而且大的不能放在小的上面。解答结果请自己运行计算,程序见尾部。面对庞大的数字(移动圆片的次数)18446744073709551615,看来,众僧们耗尽毕生精力也不可能完成金片的移动。
后来,这个传说就演变为汉诺塔游戏:
1.有三根杆子A,B,C。A杆上有若干碟子
2.每次移动一块碟子,小的只能叠在大的上面
3.把所有碟子从A杆全部移到C杆上
经过研究发现,汉诺塔的破解很简单,就是按照移动规则向一个方向移动金片:
如3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C
此外,汉诺塔问题也是程序设计中的经典递归问题。
算法思路:
1.如果只有一个金片,则把该金片从源移动到目标棒,结束。
2.如果有n个金片,则把前n-1个金片移动到辅助的棒,然后把自己移动到目标棒,最后再把前n-1个移动到目标棒
(非专业人士可以忽略以下内容)
补充:汉诺塔的算法实现(c++)
#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;
}
C语言精简算法
/* Copyrighter by SS7E */
#include<stdio.h> /* Copyrighter by SS7E */
void hanoi(int n,char A,char B,char C) /* Copyrighter by SS7E */
{
if(n==1)
{
printf("Move disk %d from %c to %c\n",n,A,C);
}
else
{
hanoi(n-1,A,C,B); /* Copyrighter by SS7E */
printf("Move disk %d from %c to %c\n",n,A,C);
hanoi(n-1,B,A,C); /* Copyrighter by SS7E */
}
}
main() /* Copyrighter by SS7E */
{
int n;
printf("请输入数字n以解决n阶汉诺塔问题:\n");
scanf("%d",&n);
hanoi(n,'A','B','C');
}/* Copyrighter by SS7E */
php算法:
<?php
function hanoi($n,$x,$y,$z){
if($n==1){
move($x,1,$z);
}else{
hanoi($n-1,$x,$z,$y);
move($x,$n,$z);
hanoi($n-1,$y,$x,$z);
}
}
function move($x,$n,$z){
echo 'move disk '.$n.' from '.$x.' to '.$z.'<br>';
}
hanoi(10,'x','y','z');
?>
java算法:
public class Haniojava
{
public static void main(String args[])
{
byte n=2;
char a='A',b='B',c='C';
hanio(n,a,b,c);
}
public static void hanio(byte n,char a,char b,char c)
{
if(n==1)
System.out.println("move "+a+" to "+b);
else
{
hanio((byte)(n-1),a,c,b);
System.out.println("move "+a+" to "+b);
hanio((byte)(n-1),c,b,a);
}
}
}
#include<iostream.h>
void move(char ch1, char ch2) {
cout<<ch1<<"->"<<ch2<<' ';
}
void hanoi(int n, char a, char b, char c) {
if (n==1)
move (a,c);
else {
hanoi (n-1,a,c,b);
move (a,c);
hanoi (n-1,b,a,c);
}
}
void main() {
int m;
cout<<"Enter the number of disk to move:\n";
cin>>m;
cout<<"The step to moving "<<m<<" disk:\n";
hanoi (m,'A','B','C');
cin>>m;
}
用不了这么复杂
,设A上有n个盘子。
如果n=1,则将圆盘从A直接移动到C。
如果n=2,则:
1.将A上的n-1(等于1)个圆盘移到B上;
2.再将A上的一个圆盘移到C上;
3.最后将B上的n-1(等于1)个圆盘移到C上。
如果n=3,则:
A. 将A上的n-1(等于2,令其为n`)个圆盘移到B(借助于C),步骤如下:
(1)将A上的n`-1(等于1)个圆盘移到C上。
(2)将A上的一个圆盘移到B。
(3)将C上的n`-1(等于1)个圆盘移到B。
B. 将A上的一个圆盘移到C。
C. 将B上的n-1(等于2,令其为n`)个圆盘移到C(借助A),步骤如下:
(1)将B上的n`-1(等于1)个圆盘移到A。
(2)将B上的一个盘子移到C。
(3)将A上的n`-1(等于1)个圆盘移到C。
到此,完成了三个圆盘的移动过程。
从上面分析可以看出,当n大于等于2时,移动的过程可分解为三个步骤:
第一步 把A上的n-1个圆盘移到B上;
第二步 把A上的一个圆盘移到C上;
第三步 把B上的n-1个圆盘移到C上;其中第一步和第三步是类同的。
当n=3时,第一步和第三步又分解为类同的三步,即把n`-1个圆盘从一个针移到另一个针上,这里的n`=n-1。 显然这是一个递归过程,据此算法可编程如下:
move(int n,int x,int y,int z)
{
if(n==1)
printf("%c-->%c\n",x,z);
else
{
move(n-1,x,z,y);
printf("%c-->%c\n",x,z);
move(n-1,y,x,z);
}
}
main()
{
int h;
printf("\ninput number:\n");
scanf("%d",&h);
printf("the step to moving %2d diskes:\n",h);
move(h,'a','b','c');
}
D. 汉诺塔的算法
算法介绍:当盘子的个数为n时,移动的次数应等于2^n–1。后来一位美国学者发现一种出人意料的简单方法,只要轮流进行两步操作就可以了。首先把三根柱子按顺序排成品字型,把所有的圆盘按从大到小的顺序放在柱子A上,根据圆盘的数量确定柱子的排放顺序:若n为偶数,按顺时针方向依次摆放A、B、C;
若n为奇数,按顺时针方向依次摆放A、C、B。
所以结果非常简单,就是按照移动规则向一个方向移动金片:如3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C
汉诺塔问题也是程序设计中的经典递归问题。
(4)汉诺塔算法的流程图扩展阅读
由来:
法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。
不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。
不管这个传说的可信度有多大,如果考虑一下把64片金片,由一根针上移到另一根针上,并且始终保持上小下大的顺序。这需要多少次移动呢?这里需要递归的方法。假设有n片,移动次数是f(n).显然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。此后不难证明f(n)=2^n-1。n=64时,
假如每秒钟一次,共需多长时间呢?一个平年365天有31536000 秒,闰年366天有31622400秒,平均每年31556952秒,计算一下:18446744073709551615秒。
这表明移完这些金片需要5845.54亿年以上,而地球存在至今不过45亿年,太阳系的预期寿命据说也就是数百亿年。真的过了5845.54亿年,不说太阳系和银河系,至少地球上的一切生命,连同梵塔、庙宇等,都早已经灰飞烟灭。
E. C语言汉诺塔问题,请问这个n=3的详细步骤是什么呀,大一新生没听懂
这是汉诺塔的算法的问题。程序本身很简单。
汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
这个主要是看算法,再一个就是递归的学习,程序本身非常简单。
F. 汉诺塔问题的递归算法流程图
关键是第一步移法,奇数层的说,3层在第一柱,后两根柱数数:123。所以,第一块应放在第二根柱,4层,第一块放第三柱。...........奇数层第一块放第二柱,偶数层第一块放第三柱。
G. 求汉诺塔递归全过程的算法详解图,记得一定要是图释哦!!!
图解是什么意思呀。
这个算法 那么简单没必要搞得那么复杂吧。
an = an-1 + 1;
你明白这个等式的意义吗?
这个等式已经包含了递归算法的全部含义。
an 表示 n个数的和,an-1 表示n-1个数的和 ,an = an-1 + 1;表示n个数的和可以通过n-1个数的和来求的。
上述说明哪些情况可以使用递归呢?
那就是:已知前一个步骤可以求得后一个步骤的结果的情况,并且前一个步骤和后一个步骤是有规律过度的。
比如汉诺塔问题:
移n个盘是已移n-1个盘为条件的,两者的共同点是移盘。所以可以用f(n)表示移n个盘,f(n-1)表示移n-1个盘,那么移n个盘和移n-1个盘有什么关系呢?
这就需要预先分析问题才能得出具体的关系
在这个问题中,把n个盘从a移到c需要三个步骤来完成。
1.n-1个盘从a移到b
2 1个盘从a移到c
3 n-1个盘从b移到c
已知n-1个盘从a移到b是可行的,为什么?
因为移1个盘是可行,那么移2个盘也是可行,移 3个盘是已移2个盘为条件的,所以移3个盘也是可行的,所以移n个 盘是可行的。
所以根据已知条件可以解得:
设f(n, a, b,c) 表示 把n个盘从a移到c 借助b --------------------------这里很关键,这是搞懂递归的关键关键。
那么把n-1个盘从a移到b 借助c 怎样表示呢?
很明显是:f(n-1, a, c,b)
那么把1个盘从a移到c怎样表示呢?
很明显是:f(1, a, b,c)
那么把n-1个盘从b移到c 借助a 怎样表示呢?
很明显是:f(n-1, b, a,c)
所以f(n, a, b,c) = ( f(n-1, a,c,b) , f(1, a, b,c), f(n-1, b,a,c))
这和等差等比数列一个原理。
没有什么 特别的。
记住是问题有这样递推关系才可以使用这种方法。
如果要你计算1+2+8+22 的结果 你就不能使用递归。
因为该问题的后一步骤与前一步骤不具有规律性,所以已知前一个步骤并不能求的后一个步骤的值
1+2+3+4 ...+
这个问题就可以使用递归
原因你懂了吧。
至于爬楼梯问题,无限级分类 问题等一些递归问题,那不过时小菜一碟。
一句话:后一步骤依赖前一步骤并且二者联系具有规律性,运用递归必然成功。
H. 汉诺塔递归算法是什么
如下:
1、汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。
大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
2、抽象为数学问题:从左到右有A、B、C三根柱子,其中A柱子上面有从小叠到大的n个圆盘,现要求将A柱子上的圆盘移到C柱子上去,期间只有一个原则:一次只能移到一个盘子且大盘子不能在小盘子上面,求移动的步骤和移动的次数。
算法分析(递归算法):
实现这个算法可以简单分为三个步骤:把n-1个盘子由A 移到 B;把第n个盘子由 A移到 C;把n-1个盘子由B 移到 C。从这里入手,在加上上面数学问题解法的分析,我们不难发现,移到的步数必定为奇数步。
1、中间的一步是把最大的一个盘子由A移到C上去。
2、中间一步之上可以看成把A上n-1个盘子通过借助辅助塔(C塔)移到了B上。
3、中间一步之下可以看成把B上n-1个盘子通过借助辅助塔(A塔)移到了C上。
I. 求七块汉诺塔完成所需步骤(不要编程,只要步骤
七块汉诺塔完成所需步骤如下:用1到7表示七个汉诺塔圆盘,圆盘半径默认为1<2<3<4<5<6<7;以ABC表示汉诺塔的三个柱子,A为最左,B为中间,C为最右;
1—C表示把1号圆盘移动到第三个柱子上,以此类推:
一、1—C;2—B;1—B;3—C;1—A;2—C;1—C;4—B;1—B;2—A;
二、1—A;3—B;1—C;2—B;1—C;5—C;1—A;2—C;1—C;3—A;
三、1—B;2—A;1—A;4—C;1—C;2—B;1—B;3—C;1—A;2—C;
四、1—C;6—B;1—B;2—A;1—A;3—B;1—C;2—B;1—B;4—A;
五、1—A;2—C;1—C;3—A;1—B;2—A;1—A;5—C;1—C;2—B;
六、1—B;3—C;1—A;2—C;1—C;4—B;1—B;2—A;1—A;3—B;
七、1—C;2—B;1—B;7—C;1—A;2—C;1—C;3—A;1—B;2—A;
八、1—A;4—C;1—C;2—B;1—B;3—C;1—A;2—C;1—C;5—A;
九、1—B;2—A;1—A;3—B;1—C;2—B;1—B;4—A;1—A;2—C;
十、1—C;3—A;1—B;2—A;1—A;6—C;1—C;2—B;1—B;3—C;
十一、1—A;2—C;1—C;4—B;1—B;2—A;1—A;3—B;1—C;2—B;
十二、1—B;5—C;1—A;2—C;1—C;3—A;1—B;2—A;1—A;4—C;
十三、1—C;2—B;1—B;3—C;1—A;2—C;1—C;
(9)汉诺塔算法的流程图扩展阅读:
汉诺塔的算法介绍
其实算法非常简单,当盘子的个数为n时,移动的次数应等于2^n – 1(有兴趣的可以自己证明试试看)。后来一位美国学者发现一种出人意料的简单方法,只要轮流进行两步操作就可以了。首先把三根柱子按顺序排成品字型,把所有的圆盘按从大到小的顺序放在柱子A上,根据圆盘的数量确定柱子的排放顺序:若n为偶数,按顺时针方向依次摆放 A B C;
若n为奇数,按顺时针方向依次摆放 A C B。
⑴按顺时针方向把圆盘1从现在的柱子移动到下一根柱子,即当n为偶数时,若圆盘1在柱子A,则把它移动到B;若圆盘1在柱子B,则把它移动到C;若圆盘1在柱子C,则把它移动到A。
⑵接着,把另外两根柱子上可以移动的圆盘移动到新的柱子上。即把非空柱子上的圆盘移动到空柱子上,当两根柱子都非空时,移动较大的圆盘。
这一步没有明确规定移动哪个圆盘,你可能以为会有多种可能性,其实不然,可实施的行动是唯一的。
⑶反复进行⑴⑵操作,最后就能按规定完成汉诺塔的移动。
所以结果非常简单,就是按照移动规则向一个方向移动金片:
如3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C
(9)汉诺塔算法的流程图扩展阅读来源:网络-汉诺塔-算法介绍
J. 汉诺塔递归算法是什么
汉诺塔问题实际上就是要将柱子A上由小到大排列的圆环按照相同的大小顺序移动到柱子C,之间的过程可以使用柱子B。
其递归的归纳思想是这样的:
(1)首先,当只有一个盘子的时候只需要将A上的1号盘子移动到C上就行了
(2)当有2个盘子在A上的时候,需要将A上的1号盘子(由上往下数)移动到B上,再将A上的2号盘子移动到C上,之后将B上的1号盘子移动到C上
(3)当有3个盘子在A上的时候,需要将A上的1号和2号盘子移动到B上(需要借助C),之后将A上的3号盘子移动到C上,再将B上的盘子移动到C上(需要借助A)
(...)以此类推
(N)当有N个盘子在A上的时候,需要将A上的N-1个盘子移动到B上(需要借助C),之后将A上的第N个盘子移动到C上,再将B上的盘子移动到C上(需要借助A)
起源
汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。
大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。