汉诺塔递归算法

5.5.2 汉诺塔递归栈
问题抽象
3个塔,n个碟子
初始:所有碟子放在1号塔,大的在底下,小的在上面
任务:把碟子移动到2号塔,顺序不变, 可用3号塔辅助
限制
每次只能移动一个碟子
总是大碟子在下,小的在上
递归解法
移动碟子的方法:move(n, t1, t2, t3)——
将n个碟子从t1移到t2,t3辅助
可分解为3个步骤
将n-1个碟子从t1移到t3:move(n-1, t1, t3, t2)
将最大的碟子从t1移到t2
将n-1个碟子从t3移到t2:move(n-1, t3, t2, t1)
汉诺塔递归程序
void TowersOfHanoi(int n, int x, int y, int z)
{// Move the top n disks from tower x to tower y.
// Use tower z for intermediate storage.
if (n > 0) {
TowersOfHanoi(n-1, x, z, y);
cout << "Move top disk from tower " << x
<< " to top of tower " << y << endl;
TowersOfHanoi(n-1, z, y, x);}
}

moves(n)=2n-1——最少次数,Θ(2n)
一般递归程序转换为循环
递归函数主体的转换
转换为循环,while(1)即可
递归调用的转换
将当前参数、局部变量…(活动记录)压栈
参照调用方式改变参数,继续循环
函数执行结束——递归返回的处理
若栈空,整个递归过程结束,跳出循环
否则,将调用者的活动记录弹出栈,恢复其环境,继续循环
递归函数不同入口的区分——返回地址的处理
上例:ENTRANCE、FIRST、SECOND
活动记录的一部分,与参数、局部变量一同压栈、出栈
在循环主体中,根据当前活动记录的入口值,执行不同代码
汉诺塔的递归栈实现
#include
#include
#include
#include
#include

using namespace ::std;
enum {
ENTRANCE = 0,
FIRST,
SECOND
};
struct ac {
int n, x, y, z;
int r;
};
汉诺塔的递归栈实现
void hanoi(int n, int x, int y, int z)
{
stack stack;
struct ac ac = { n, x, y, z, ENTRANCE };
while (1)
{
if (ac.n <= 0)
{
if (stack.empty())
break;
ac = stack.top();
stack.pop();
if (ac.r == ENTRANCE)
ac.r = FIRST;
else
ac.r = SECOND;
}
汉诺塔递归栈实现
if (ac.r == ENTRANCE)
{
stack.push(ac);
ac.n--;
swap(ac.y, ac.z);
}
else if (ac.r == FIRST)
{
cout << "Move top disk from tower " << ac.x
<< " to top of tower " << ac.y << endl;
stack.push(ac);
ac.r = ENTRANCE;
ac.n--;
swap(ac.x, ac.z);
}
汉诺塔递归栈实现
else if (ac.r == SECOND)
{
if (stack.empty())
break;
ac = stack.top();
stack.pop();
if (ac.r == ENTRANCE)
ac.r = FIRST;
else
ac.r = SECOND;
}
}
}
汉诺塔递归栈实现
int main(int argc, char *argv[])
{
int n;

scanf("%d", &n);
hanoi(n, 1, 2, 3);
return 0;
}

合集下载

汉诺塔原理

汉诺塔原理

汉诺塔原理汉诺塔(Tower of Hanoi)是一个经典的数学问题,它源自印度的一个古老传说。

传说中,在贝拿勒斯(Benares)的圣庙里,一块黄铜板上插着三根宝石针。

初始时,所有的圆盘都放在一根针上,小的在上,大的在下。

这些圆盘按从小到大的次序排列。

有一个僧侣的职责是把这些圆盘从一个针移到另一个针上。

在移动过程中,可以借助第三根针,但有一个条件,就是在小的圆盘上不能放大的圆盘。

当所有的圆盘都从一根针上移到另一根针上时,这个世界就将毁灭。

汉诺塔问题的数学模型是,设有n个圆盘和三根柱子(我们称之为A、B、C),开始时所有的圆盘都叠在柱子A上,按照大小顺序从上到下叠放。

要求把所有的圆盘从柱子A移动到柱子C上,期间可以借助柱子B,但有一个限制条件,任何时刻都不能把一个大的圆盘放在一个小的圆盘上面。

汉诺塔问题的解法是一个典型的递归算法。

整个移动过程可以分解为三个步骤:1. 把n-1个圆盘从柱子A经过柱子C移动到柱子B上;2. 把第n个圆盘从柱子A移动到柱子C上;3. 把n-1个圆盘从柱子B经过柱子A移动到柱子C上。

这个过程可以用递归的方式来描述。

当我们解决n-1个圆盘的问题时,可以再次把它分解为n-2个圆盘的问题,直到最后只剩下一个圆盘的问题,这就是递归的思想。

递归算法虽然简洁,但是在实际应用中需要注意避免出现栈溢出的情况。

除了递归算法外,汉诺塔问题还有非递归的解法。

可以利用栈来模拟递归的过程,将每一步的移动操作保存在栈中,依次执行,直到所有的圆盘都移动到目标柱子上。

汉诺塔问题不仅是一个数学问题,更是一个思维训练的好题目。

它可以锻炼人的逻辑思维能力和动手能力。

在计算机科学中,递归算法是一种非常重要的思想,很多经典的算法问题都可以用递归的方式来解决。

总之,汉诺塔问题是一个古老而经典的数学问题,它不仅有着深奥的数学原理,更能锻炼人的思维能力。

通过研究汉诺塔问题,我们可以更好地理解递归算法的原理,提高自己的编程能力和解决问题的能力。

汉诺塔函数

汉诺塔函数

汉诺塔函数
汉诺塔函数,又称为河内塔函数,是一种经典的递归算法。

该算法的目的是将一堆盘子从一个柱子移动到另一个柱子,同时遵循以下规则:
1. 每次只能移动一个盘子;
2. 每次移动必须将盘子从较小的柱子移动到较大的柱子上;
3. 每个盘子只能放在比它大的盘子上面。

汉诺塔函数的实现过程是将问题分解成更小的问题,通过递归的方式解决。

具体实现方法如下:
1. 如果只有一个盘子,直接将它移动到目标柱子上;
2. 如果有多个盘子,将它们看作两部分:最底下的一个盘子和上面的所有盘子。

先将上面的所有盘子移动到辅助柱子上,再将最底下的盘子移动到目标柱子上,最后将辅助柱子上的盘子移动到目标柱子上。

通过反复执行上述操作,即可将所有盘子从起始柱子移动到目标柱子上。

汉诺塔函数是一种经典的递归算法,具有较高的实用价值。

在程序设计中,我们可以通过该函数解决一些具有相似结构的问题,如排序、搜索等。

- 1 -。

三座塔问题---已测试

三座塔问题---已测试

三座塔问题---已测试
问题背景
三座塔问题是一个经典的数学思维问题,旨在通过逻辑推理找出正确答案。

这个问题有多个版本,但基本思路相同。

以下是问题的一个例子:
在一个互相垂直的平面上,有三座高塔,分别编号为A、B和C。

这三座塔上放置着不同尺寸的环,形成了一个由大到小的环序列。

现在需要将这些环从塔A移动到塔C,但在移动过程中必须遵守以下规则:
1. 一次只能移动一个环;
2. 大环不能放在小环上面。

解决方案
为了解决三座塔问题,我们可以采用经典的递归算法,称为汉诺塔算法。

例如,当只有一个环时,我们可以直接将它从塔A移动到塔C。

对于有两个环的情况,我们可以按照以下步骤进行操作:
1. 从塔A将最小的环移动到塔B(空塔);
2. 从塔A将剩下的大环移动到塔C;
3. 从塔B将最小的环移动到塔C。

当有三个环时,我们可以按照以下步骤进行操作:
1. 从塔A将最小的两个环移动到塔B(空塔);
2. 从塔A将最大的环移动到塔C;
3. 从塔B将最小的两个环移动到塔C。

通过不断递归地运用上述步骤,我们可以解决任意数量环的三
座塔问题。

时间复杂度分析
汉诺塔算法的时间复杂度可以表示为O(2^n),其中n为环的数量。

由于递归的特性,每次移动一个环都会产生两个新的子问题,因此问题的规模呈指数级增长。

测试结果
在对三座塔问题进行测试时,我们发现无论输入的环数量是多少,都能正确地将环从塔A移动到塔C,并且符合问题的要求。

因此,我们可以确认该解决方案有效。

6种基本算法 递归

6种基本算法 递归

6种基本算法递归递归是一种重要的算法思想,它在计算机科学中得到广泛应用。

本文将介绍六种基本的递归算法,并对其原理和应用进行讲解。

一、递归的基本概念递归是指一个函数在其定义中调用自身的过程。

递归算法通过将一个大问题划分为一个或多个相同或相似的子问题,然后通过解决子问题来解决原始问题。

递归算法具有简洁、优雅以及可读性强的特点,但同时也需要注意递归的停止条件,以避免无限递归的发生。

二、阶乘算法阶乘算法是递归算法中最经典的例子之一。

它的定义如下:```n! = n * (n-1) * (n-2) * ... * 1```其中,n为一个非负整数。

阶乘算法可以通过递归的方式实现,即:```fact(n) = n * fact(n-1)```其中,停止条件为`n=0`时,返回1。

三、斐波那契数列算法斐波那契数列是一个无限序列,其定义如下:```F(0) = 0F(1) = 1F(n) = F(n-1) + F(n-2) (n>1)```斐波那契数列算法可以通过递归的方式实现,即:```fib(n) = fib(n-1) + fib(n-2)```其中,停止条件为`n=0`或`n=1`时,返回相应的值。

四、二分查找算法二分查找算法是一种高效的查找算法,它的基本原理是将已排序的数组分成两部分,然后判断目标值在哪一部分,并继续在该部分中进行查找,直到找到目标值或者查找范围为空。

二分查找算法可以通过递归的方式实现,即:```binarySearch(arr, target, start, end) = binarySearch(arr, target, start, mid-1) (target < arr[mid])= binarySearch(arr, target, mid+1, end) (target > arr[mid])= mid (target = arr[mid])```其中,`arr`为已排序的数组,`target`为目标值,`start`和`end`为查找范围的起始和结束位置。

汉诺塔问题数学解法

汉诺塔问题数学解法

汉诺塔问题数学解法
一、建立递归模型
汉诺塔问题是一个经典的递归问题,可以通过建立递归模型来求解。

递归模型的基本思想是将问题分解为更小的子问题,然后通过对子问题的求解来得到原问题的解。

二、定义变量
在汉诺塔问题中,我们可以定义以下变量:
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个盘子从辅助柱子移动到目标柱子。

五、验证解决方案
通过以上规律,我们可以得到汉诺塔问题的解法。

为了验证解法的正确性,我们可以使用递归函数来实现解法,并使用测试数据来验证解法的正确性。

汉诺塔的时间复杂度递推公式

汉诺塔的时间复杂度递推公式

汉诺塔的时间复杂度递推公式
汉诺塔问题是一个数学谜题,也是计算机科学中经典的问题之一。

汉诺塔问题需要将一堆盘子从一个柱子移动到另一个柱子,规则是每次只能移动一个盘子,并且大盘子不能放在小盘子上面。

汉诺塔问题在算法分析中具有重要性,因为它能够展示递归算法的应用。

在汉诺塔问题中,我们可以通过递归算法来解决。

假设我们有n 个盘子,它们被放置在柱子A上。

我们需要将它们全部移动到柱子C 上。

我们定义递归函数hanoi(n,A,B,C)表示将n个盘子从柱子A移
动到柱子C,其中B表示辅助柱子。

递归函数hanoi(n,A,B,C)的时间复杂度可以使用递推公式来表示:
T(n) = 2T(n-1) + 1
其中T(n-1)表示n-1个盘子从A移动到B所需的时间,2T(n-1)表示将n-1个盘子从A移动到B,再将最大的盘子从A移动到C,最
后将n-1个盘子从B移动到C所需的时间,1表示将最大的盘子从A
移动到C所需的时间。

由此递推得到时间复杂度:
T(n) = 2^n - 1
因此,汉诺塔问题的时间复杂度为指数级别,随着盘子数量的增加,时间复杂度增长非常快。

- 1 -。

汉诺塔解决方案(3篇)

第1篇引言汉诺塔问题是一个经典的递归问题,起源于印度的一个古老传说。

它描述了三个柱子,其中第一个柱子上放置了若干个大小不同的盘子,要求按照一定的规则将所有的盘子移动到第三个柱子上。

在这个过程中,每个盘子只能放在一个柱子上,且在移动过程中,大盘子不能放在小盘子上面。

汉诺塔问题不仅是一个有趣的数学游戏,也是一个很好的递归算法示例。

本文将详细介绍汉诺塔问题的背景、规则、递归解法以及非递归解法,并探讨一些优化策略。

一、汉诺塔问题的背景与规则1. 背景故事汉诺塔问题源于印度的一个古老传说。

相传,在古印度有一个神庙,庙中有一个由三根柱子组成的塔,塔上有64个金盘子,按照从小到大的顺序依次放置。

神庙的僧侣们每天的工作就是将盘子按照一定的规则从一根柱子移动到另一根柱子上。

当所有的盘子都移动到第三个柱子上时,世界末日就会到来。

2. 游戏规则(1)每次只能移动一个盘子;(2)大盘子不能放在小盘子上面;(3)每次移动盘子后,都要将盘子放在柱子的顶部。

二、汉诺塔问题的递归解法1. 递归思想递归是一种常用的算法设计方法,它通过将复杂问题分解为更小的子问题来求解。

汉诺塔问题的递归解法基于以下思想:(1)将n-1个盘子从第一个柱子移动到第二个柱子;(2)将最大的盘子从第一个柱子移动到第三个柱子;(3)将n-1个盘子从第二个柱子移动到第三个柱子。

2. 递归解法步骤(1)定义一个递归函数,如hanoi(n, source, target, auxiliary),其中n表示盘子的数量,source表示源柱子,target表示目标柱子,auxiliary表示辅助柱子;(2)当n=1时,直接将盘子从source柱子移动到target柱子;(3)当n>1时,先递归调用hanoi(n-1, source, auxiliary, target),将n-1个盘子从source柱子移动到auxiliary柱子;(4)将最大的盘子从source柱子移动到target柱子;(5)递归调用hanoi(n-1, auxiliary, target, source),将n-1个盘子从auxiliary柱子移动到target柱子。

汉诺塔的非递归算法

汉诺塔的⾮递归算法思路模拟递归程序执⾏过程,借助⼀个堆栈,把递归转成⾮递归算法。

转化过程1. 递归算法1void hanoi(int n, char from, char pass, char to) {2if (n == 0)3return;45 hanoi(n - 1, from, to, pass);6 move(n, from, to);7 hanoi(n - 1, pass, from, to);8 }2. 处理⾸递归 本函数第2⾏是结束条件,第5⾏开始进⼊⾸递归。

执⾏第5⾏函数调⽤之前,需要保留调⽤现场,本例中是4个参数⼊栈,使⽤新的参数调⽤hanoi函数。

⽽继续跟踪被调⽤的函数,可以看出需要⼀直进⾏⼊栈操作,直到参数n == 0为⽌。

对此⾏为,我们可以⽤⼀个循环来模拟:伪代码:int i = n;while (i != 0) { push(i);i --;} 现在可以断⾔ i ==0 ,满⾜函数返回的条件。

当函数返回后,需要通过pop操作来恢复现场,然后继续执⾏后⾯的语句。

为了简化问题,我们假设后⾯只有move()⼀条语句,执⾏完毕该语句后就继续向上⼀层回溯,直⾄最顶层,这样⼜可以⽤⼀个循环来模拟:伪代码:int i = n;while (i != 0) { push(i);i --;}while (栈不空) {int m = pop();move(m, ...);尾递归...}3. 处理尾递归 ⼀般⽽⾔,尾递归可以直接改成上⼀条语句的循环。

但在本例中,尾递归被嵌在另⼀个循环中,此时需要模拟它的⾏为:进⼊尾递归hanoi()函数后,需要执⾏其函数体,⽽函数体⼜是上述代码中的第⼀句话,可以如下表⽰:伪代码:a_new_beginning:int i = n;while (i != 0) { push(i);i --;}while (栈不空) {int m = pop();move(m, ...);产⽣新的参数,跳出循环,跳转到a_new_beginning语句处;} 相⽐于第⼀个while全部执⾏,第⼆个while实际只被执⾏⼀次就跳出来了,这种结构,很显然可以等价变换为外加⼀个⼤循环。

汉诺塔游戏:递归经典问题

汉诺塔游戏:递归经典问题汉诺塔游戏,是非常著名的智力趣味题,在很多算法书籍和智力竞赛中都有涉及。

汉诺塔游戏的基本规则是:在一块板子上,有三根编号分别为A、B、C的杆,在A杆上按自下而上、由大到小的顺序放置着64个(或其他数目)圆盘,每次只能移动一个圆盘,并且在移动过程中三根杆上都始终保持大盘在下、小盘在上的状态,操作过程中圆盘可以在A、B、C任意一杆上,要如何把A杆上的圆盘全部移到C杆上?以3个圆盘为例:将3个圆盘按由小到大的顺序分别记作P1、P2、P3。

按照规则将三个圆盘从A杆移至C杆,则需以下步骤:(1)先将P1移至C杆,再将P2移至B杆,然后将P1移至B杆,此时P1和P2均在B杆上(需3步);(2)将P3移至C杆(需1步);(3)将P1移至A杆,将P2移至C杆,最后将P1移至C杆(需3步)。

在此过程中,要将P3移至C杆,先将C杆当作中介,将P1移至C杆;再将P1、P2先移至B杆,借用B杆做中介;再将P2移至C杆时,又先将P1移至A杆,借用了A杆做中介。

(总共7步完成)以此为例,如何完成其他数量圆盘的移动操作呢?当n=1时,只需将编号为1的圆盘从A柱直接移至C柱上即可。

当n=2时,利用B柱作为辅助柱,先将圆盘1移至B柱,再将圆盘2由A柱直接移至C柱,然后再将圆盘1由B柱移至C柱。

当n=3时,同样利用B柱作为辅助柱,依照上述原则,先设法将圆盘1、2移至B柱,待圆盘3由A柱移至C柱后,再依照上述原则设法将圆盘1、2移至C柱。

......依此类推,当n>1时,需利用B柱作为辅助柱,先设法将压在编号为n的圆盘上的n-1个圆盘从A柱(依照上述原则)移至C柱,待编号为n的圆盘从A柱移至C柱后,再将B柱上的n-1个圆盘(依照上述原则)移至C柱。

游戏的移动操作很简单,但是如何将64个圆盘从一根杆子上移到另一根杆子上,并且始终保持上小下大的顺序,一共需要移动多少次才是让人头疼的问题。

游戏过程中不难发现:不管把哪一个圆盘移到另一根杆子上,移动的次数都要比移动上面一个增加一倍。

汉诺塔规律总结

汉诺塔规律总结汉诺塔是一个古老而富有智慧的益智游戏,也是程序设计中经典的递归例子之一。

虽然最初是一个故事中的谜题,但在计算机领域中找到了广泛的应用。

在这篇文章中,我将总结汉诺塔的规律,并解释其中的原理和应用。

一、汉诺塔的起源与规则简介汉诺塔的起源可以追溯到古老的印度传说。

根据传说,这个益智游戏最初是由寺庙里的僧侣发明的。

汉诺塔由三个柱子和一组不同大小的圆盘组成。

这些圆盘按照从大到小的顺序放在柱子上,最大的在底部,最小的在顶部。

游戏的目标是将所有的圆盘从一个柱子移动到另一个柱子,但在移动过程中必须遵循以下规则:1. 只能移动一个圆盘;2. 每次移动必须将圆盘放在一个比它大的圆盘上;3. 可以用第三个柱子作为中转。

这些规则看似简单,但实际上引出了许多有趣的数学和计算问题。

二、汉诺塔的递归解法在解决汉诺塔问题时,递归是最常用的方法。

递归是一种解决问题的思维方式,通过将一个大问题拆分成若干个相同或相似的子问题来求解。

汉诺塔问题的递归解决方案如下:1. 如果只有一个圆盘,直接将它从源柱子移动到目标柱子;2. 如果有多个圆盘,那么先将上面的 n-1 个圆盘从源柱子移动到辅助柱子;3. 然后将最大的圆盘从源柱子移动到目标柱子;4. 最后将 n-1 个圆盘从辅助柱子移动到目标柱子。

这个递归算法非常巧妙。

通过将问题分解成更小的子问题,我们可以很容易地解决每个子问题,并将它们组合起来得到整个问题的解答。

值得注意的是,汉诺塔的递归解法的时间复杂度为O(2^n),因此在处理大规模问题时需要注意效率。

三、汉诺塔的数学规律通过观察汉诺塔的移动过程,我们可以发现一些有趣的数学规律。

这些规律对于理解问题和设计算法都非常有帮助。

1. 最少步数:对于汉诺塔问题,移动 n 个圆盘最少需要 2^n - 1 步。

这个结论可以通过数学归纳法来证明,但超出了本文的范围。

2. 移动顺序的规律:如果将汉诺塔问题划分为奇数和偶数个圆盘两种情况,我们可以观察到移动的规律:2.1 奇数个圆盘的情况下,移动的顺序为:源柱子 -> 辅助柱子 ->目标柱子;2.2 偶数个圆盘的情况下,移动的顺序为:源柱子 -> 目标柱子 ->辅助柱子 -> 目标柱子。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档