C++递归函数汉诺塔原理一步步详解
- 格式:pdf
- 大小:79.79 KB
- 文档页数:3
证明并推导汉诺塔(河内之塔)问题公式本⽂链接: 第⼀次遇到汉诺塔问题时我瞬间就被搞蒙了之后果断扔下不管了,今天再次遇到这个问题被搞蒙again ,在⽹上搜了好久愣是没让我找到证明汉诺塔问题可解和推导公式过程的资料,于是花了⼏个⼩时(谁让咱不太聪明呢,嘿嘿),最后终于想通了,记录下来希望对像我⼀样不聪明的⼈有所帮助。
证明可解汉诺塔问题:我⽤的是数学归纳法,假设圆盘的个数为n ,圆盘编号从上到下依次为1,2,3,4,……n ,证明如下①当 n = 1 时,从 A 移动到 C 显然能够完成,设需要移动的次数是a 。
②当 n = 2 时,由①可知从把 1 号盘⼦从 A 移动到 B 能够完成(B 和 C 是等效的)此时移动次数为a 。
之后把2号盘⼦移动到C 上⾯此时移动次数为a + 1。
这时把1号盘⼦从B 移动到C 和①是等价的,移动后总的移动次数是a = a + 1 + a 。
③当n = 3时,由②可知移动成下图的效果是可以实现的,此时移动的次数是a2,接着把3号盘⼦移动到C 上⾯此时移动的次数是a + 1,这时把1和2号盘⼦移动到C 上⾯(移动过程中3号盘⼦始终不会动)和②等效的,移动完成之后如下移动的总次数是a = a + 1 + a ④当n=4时,由③可知移动成下图的效果是可以实现的,此时移动的次数是a 把4号盘⼦从A 移动到C此时移动的次数是a + 1接下来把123号盘⼦从B 移动到C 的过程⼜和③等效了移动之后如下移动的总次数是a = a + 1 + a 假设当n= k 时,从A 移动到C 是可以实现的,那么当n=k+1时,可以移动到A 上⾯只剩k+1号盘⼦,B 上⾯依次是1,2,3,.....,k 号盘字,此时移动次数是a把k+1号盘⼦移动到C 上⾯,这时移动次数是a + 1接下来和n=k 时移动过程等效,移动完成后移动总次数是a = a + 1+ a可以得知移动k+1个盘⼦需要的次数与移动k 个盘⼦的次数之间的关系是:a = a + 1+ a = 2a + 1111 2 1 12 3 2 233 4 3 3k k k+1k kk+1 k k k所以a + 1 = 2*(a + 1)【这是个等⽐数列⾼中学过的】即a + 1 = (a1 +1)* 2 = 2 因此a = 2 - 1⾄此,证明完毕。
【C语⾔程序设计】汉诺塔问题,⽤C语⾔实现汉诺塔!汉诺塔问题是指:⼀块板上有三根针 A、B、C。
A 针上套有 64 个⼤⼩不等的圆盘,按照⼤的在下、⼩的在上的顺序排列,要把这 64 个圆盘从 A 针移动到 C 针上,每次只能移动⼀个圆盘,移动过程可以借助 B 针。
但在任何时候,任何针上的圆盘都必须保持⼤盘在下,⼩盘在上。
从键盘输⼊需移动的圆盘个数,给出移动的过程。
算法思想对于汉诺塔问题,当只移动⼀个圆盘时,直接将圆盘从 A 针移动到 C 针。
若移动的圆盘为 n(n>1),则分成⼏步⾛:把 (n-1) 个圆盘从 A 针移动到 B 针(借助 C 针);A 针上的最后⼀个圆盘移动到 C 针;B 针上的 (n-1) 个圆盘移动到 C 针(借助 A 针)。
每做⼀遍,移动的圆盘少⼀个,逐次递减,最后当 n 为 1 时,完成整个移动过程。
因此,解决汉诺塔问题可设计⼀个递归函数,利⽤递归实现圆盘的整个移动过程,问题的解决过程是对实际操作的模拟。
程序代码#include <stdio.h>int main(){int hanoi(int,char,char,char);int n,counter;printf("Input the number of diskes:");scanf("%d",&n);printf("\n");counter=hanoi(n,'A','B','C');return0;}int hanoi(int n,char x,char y,char z){int move(char,int,char);if(n==1)move(x,1,z);else{hanoi(n-1,x,z,y);move(x,n,z);hanoi(n-1,y,x,z);}return0;}int move(char getone,int n,char putone){static int k=1;printf("%2d:%3d # %c---%c\n",k,n,getone,putone);if(k++%3==0)printf("\n");return0;}调试运⾏结果:当移动圆盘个数为 3 时,具体移动步骤如下所⽰:Input the number of diskes:31: 1 # A---C2: 2 # A---B3: 1 # C---B4: 3 # A---C5: 1 # B---A6: 2 # B---C7: 1 # A---C总结:本实例中定义的 hanoi() 函数是⼀个递归函数,它有四个形参"n""x""y""z"。
汉诺塔原理
汉诺塔原理是一种经典的数学问题,它涉及到如何将一堆盘子从一个柱子上移动到另一个柱子上,而且要保证每个盘子的顺序不变。
这个问题看似简单,但实际上却涉及到很多数学原理和技巧。
我们需要了解汉诺塔问题的基本规则。
假设有三个柱子,分别为A、
B、C,其中A柱子上有n个盘子,从上到下依次编号为1、2、
3、……、n。
我们的目标是将这n个盘子从A柱子上移动到C柱子上,每次只能移动一个盘子,并且不能将大盘子放在小盘子上面。
接下来,我们可以通过递归的方式来解决汉诺塔问题。
具体来说,我们可以将问题分解为三个子问题:将n-1个盘子从A柱子上移动到B柱子上;将第n个盘子从A柱子上移动到C柱子上;将n-1个盘子从B柱子上移动到C柱子上。
这样,我们就可以通过递归的方式来解决汉诺塔问题。
汉诺塔原理不仅仅是一种数学问题,它还具有很多实际应用。
例如,在计算机科学中,汉诺塔问题被广泛应用于算法设计和数据结构的研究中。
此外,汉诺塔问题还可以用来解决其他问题,例如排序、搜索、图形处理等。
汉诺塔原理是一种非常有趣和有用的数学问题,它不仅可以帮助我们提高数学思维能力,还可以帮助我们解决实际问题。
如果你对数
学感兴趣,不妨尝试一下汉诺塔问题,相信你一定会有很多收获。
汉诺塔问题求解思路汉诺塔问题是⼀个经典的问题。
汉诺塔(Hanoi Tower),⼜称河内塔,源于印度⼀个古⽼传说。
⼤梵天创造世界的时候做了三根⾦刚⽯柱⼦,在⼀根柱⼦上从下往上按照⼤⼩顺序摞着64⽚黄⾦圆盘。
⼤梵天命令婆罗门把圆盘从下⾯开始按⼤⼩顺序重新摆放在另⼀根柱⼦上。
并且规定,任何时候,在⼩圆盘上都不能放⼤圆盘,且在三根柱⼦之间⼀次只能移动⼀个圆盘。
问应该如何操作?分析如果是初次接触类似的问题,乍看之下肯定会感觉⽆从下⼿。
要把64个圆盘从a柱⼦移动到c柱⼦上,第⼀步应该怎么做?虽然可以肯定,第⼀步唯⼀的选择是移动a最上⾯的那个圆盘,但是应该将其移到b还是c呢?很难确定。
因为接下来的第⼆步、第三步……直到最后⼀步,看起来都是很难确定的。
能⽴即确定的是最后⼀步:最后⼀步的盘⼦肯定也是a最上⾯那个圆盘,并且是由a或b移动到c——此前已经将63个圆盘移动到了c上。
也许你会说,管他呢,先随便试着移动⼀下好了。
如果你这么做,你会发现,接下来你会⾯临越来越多类似的选择,对每⼀个选择都“试”⼀下的话,你会偏离正确的道路越来越远,直到你发现你接下来⽆法进⾏为⽌。
如果将这个问题的盘⼦数量减为10个或更少,就不会有太⼤的问题了。
但盘⼦数量为64的话,你⼀共需要移动约1800亿亿步(18,446,744,073,709,551,615),才能最终完成整个过程。
这是⼀个天⽂数字,没有⼈能够在有⽣之年通过⼿动的⽅式来完成它。
即使借助于计算机,假设计算机每秒能够移动100万步,那么约需要18万亿秒,即58万年。
将计算机的速度再提⾼1000倍,即每秒10亿步,也需要584年才能够完成。
注:在我的笔记本电脑上,每秒⼤约能够移动6~8百万步。
虽然64个盘⼦超出了⼈⼒和现代计算机的能⼒,但⾄少对于计算机来说,这不是⼀个⽆法完成的任务,因为与我们⼈类不同,计算机的能⼒在不断提⾼。
分解问题⼀股脑地考虑每⼀步如何移动很困难,我们可以换个思路。
汉诺塔问题数学解法
一、建立递归模型
汉诺塔问题是一个经典的递归问题,可以通过建立递归模型来求解。
递归模型的基本思想是将问题分解为更小的子问题,然后通过对子问题的求解来得到原问题的解。
二、定义变量
在汉诺塔问题中,我们可以定义以下变量:
n:表示盘子的数量;
A、B、C:表示三个柱子,其中A柱子是起始柱子,B 柱子是辅助柱子,C柱子是目标柱子;
m:表示当前需要移动的盘子数量。
三、递归关系
汉诺塔问题的递归关系可以表示为:
将m个盘子从A移动到C,需要先将m-1个盘子从A移动到B,然后将最后一个盘子从A移动到C,最后将m-1个盘子从B移动到C。
将m个盘子从A移动到B,需要先将m-1个盘子从A移动到C,然后将最后一个盘子从A移动到B,最后将m-1个盘子从C移动到B。
将m个盘子从B移动到C,需要先将m-1个盘子从B移动到A,然后将最后一个盘子从B移动到C,最后将m-1个盘子从A移动到C。
四、寻找规律
通过观察递归关系,我们可以发现以下规律:
每次移动都需要经过三个柱子,即起始柱子、辅助柱子和目标柱子;
每次移动都需要将n-1个盘子从起始柱子移动到辅助柱子,然后将最后一个盘子从起始柱子移动到目标柱子,最后将n-1个盘子从辅助柱子移动到目标柱子;
每次移动都需要将n-1个盘子从起始柱子移动到辅助柱子,然后将最后一个盘子从起始柱子移动到目标柱子,最后将n-1个盘子从辅助柱子移动到目标柱子。
五、验证解决方案
通过以上规律,我们可以得到汉诺塔问题的解法。
为了验证解法的正确性,我们可以使用递归函数来实现解法,并使用测试数据来验证解法的正确性。
汉诺塔递归算法及详解
汉诺塔(Tower of Hanoi)是一个经典的数学谜题和递归问题。
它由三个塔杆和一些不同大小的圆盘组成,开始时圆盘按从大到小的顺序叠放在一个塔杆上。
目标是将所有圆盘从起始塔杆移动到目标塔杆上,同时遵守以下规则:
1. 一次只能移动一个圆盘。
2. 任何时刻,大的圆盘不能放在小的圆盘上面。
递归算法是解决汉诺塔问题的常用方法。
其基本思想是将问题分解为较小规模的子问题,然后通过递归地解决子问题来解决原问题。
以下是汉诺塔递归算法的详解:
1. 如果只有一个圆盘需要移动,则直接将圆盘从起始塔杆移动到目标塔杆上。
2. 如果有多个圆盘需要移动,则按以下步骤进行操作:
- 将除最下方的圆盘以外的上方圆盘从起始塔杆移动到辅助塔杆上。
这可以通过递归调用解决较小规模的子问题来实现,即将上方圆盘从起始塔杆移动到目标塔杆上(目标塔杆作为新的辅助塔杆)。
- 然后将最下方的圆盘从起始塔杆直接移动到目标塔杆上。
- 最后,将辅助塔杆上的所有圆盘移动到目标塔杆上,这可以通过递归调用解决较小规模的子问题来实现,即将上方圆盘从辅助塔杆移动到起始塔杆上(起始塔杆作为新的目标塔杆)。
通过递归地应用以上步骤,就可以实现将所有圆盘从起始塔杆移动到目标塔杆上的操作。
数据结构求解汉诺塔问题的递归算法汉诺塔问题是一个经典的数学问题,它可以通过递归算法来求解。
在这个问题中,我们需要将一堆盘子从一个柱子移动到另一个柱子,同时遵守以下规则:一次只能移动一个盘子,大盘子不能放在小盘子上面。
为了解决这个问题,我们可以使用数据结构中的栈来模拟柱子的堆叠。
我们可以将每个柱子表示为一个栈,每个盘子表示为一个元素。
初始时,所有的盘子都在第一个柱子上,我们需要将它们移动到第三个柱子上。
下面是求解汉诺塔问题的递归算法的伪代码:```1. 定义一个函数hanoi,接受参数n、起始柱子A、辅助柱子B、目标柱子C2. 如果n等于1,则直接将盘子从A移动到C3. 否则,将n-1个盘子从A移动到B,借助C作为辅助柱子4. 将第n个盘子从A移动到C5. 将n-1个盘子从B移动到C,借助A作为辅助柱子```接下来,我们来详细解释一下这个算法。
首先,我们定义了一个函数hanoi,它接受四个参数:n表示盘子的数量,起始柱子A、辅助柱子B和目标柱子C。
在函数内部,我们首先判断如果n等于1,那么我们直接将盘子从A移动到C即可。
这是递归算法的终止条件。
如果n大于1,我们需要将n-1个盘子从A移动到B,借助C作为辅助柱子。
这一步是通过递归调用hanoi函数来实现的。
在递归调用中,我们将n-1作为新的盘子数量,A作为起始柱子,B作为目标柱子,C作为辅助柱子。
接下来,我们将第n个盘子从A移动到C。
这一步是直接操作的,不需要递归调用。
最后,我们需要将n-1个盘子从B移动到C,借助A作为辅助柱子。
同样地,我们通过递归调用hanoi函数来实现这一步。
在递归调用中,我们将n-1作为新的盘子数量,B作为起始柱子,C作为目标柱子,A作为辅助柱子。
通过这样的递归调用,我们可以将所有的盘子从起始柱子A移动到目标柱子C,同时遵守汉诺塔问题的规则。
总结起来,数据结构中的栈可以很好地模拟汉诺塔问题中的柱子堆叠,而递归算法则可以很好地解决这个问题。
c语言汉诺塔问题递归步骤汉诺塔问题是一个经典的递归问题,涉及将一组圆盘从一个塔移到另一个塔,其中有三个塔:源塔、目标塔和辅助塔。
汉诺塔问题的规则如下:1. 只能一次移动一个圆盘。
2. 大盘不能放在小盘上面。
递归解法的基本思路是将问题分解为更小的子问题。
以下是C语言中的递归解法步骤:```c#include <stdio.h>// 汉诺塔函数,n是圆盘数量,source是源塔,target是目标塔,auxiliary是辅助塔void hanoi(int n, char source, char target, char auxiliary) {// 基本情况:只有一个圆盘时直接移动到目标塔if (n == 1) {printf("Move disk 1 from %c to %c\n", source, target);return;}// 递归步骤// 1. 将n-1 个圆盘从源塔移动到辅助塔hanoi(n - 1, source, auxiliary, target);// 2. 将第n 个圆盘从源塔移动到目标塔printf("Move disk %d from %c to %c\n", n, source, target);// 3. 将n-1 个圆盘从辅助塔移动到目标塔hanoi(n - 1, auxiliary, target, source);}int main() {int n;printf("Enter the number of disks: ");scanf("%d", &n);// 调用汉诺塔函数hanoi(n, 'A', 'C', 'B');return 0;}```在这个例子中,`hanoi` 函数是递归的核心,它将问题分解为三个步骤:将n-1 个圆盘从源塔移动到辅助塔,将第n 个圆盘从源塔移动到目标塔,最后将n-1 个圆盘从辅助塔移动到目标塔。
c++汉诺塔问题递归算法汉诺塔问题是经典的递归问题,它可以帮助我们理解和掌握递归算法的思想。
在C++中,我们可以通过递归来解决汉诺塔问题。
汉诺塔问题的描述如下:有三根柱子A、B、C,A柱子上有n 个盘子,盘子的大小不一,大的在下,小的在上。
现在要将A 柱子上的盘子移动到C柱子上,并且每次只能移动一个盘子,并且大的盘子不能放在小的盘子上面。
要求通过借助柱子B来实现移动。
下面我们先给出解决汉诺塔问题的递归代码:```cpp#include <iostream>void hanoi(int n, char A, char B, char C) {if (n == 1) {std::cout << "Move disk 1 from " << A << " to " << C << std::endl;return;}hanoi(n - 1, A, C, B);std::cout << "Move disk " << n << " from " << A << " to " << C << std::endl;hanoi(n - 1, B, A, C);}int main() {int n = 3; // 盘子的个数hanoi(n, 'A', 'B', 'C');return 0;}```上面的代码使用了递归的思想来解决汉诺塔问题。
函数`hanoi()`接受四个参数,n表示盘子的个数,A、B、C表示三根柱子的名称。
当n等于1时,表示只有一个盘子需要移动,直接将它从A柱子移动到C柱子即可。
当n大于1时,我们可以把问题简化为两个步骤:将n-1个盘子从A柱子通过借助C柱子移动到B柱子,然后将最后一个盘子从A柱子移动到C柱子,最后将n-1个盘子从B柱子通过借助A柱子移动到C 柱子。