汉诺塔问题的递归和非递归算法

带你理解 Hanoi 汉诺塔递归算法 一. 由游戏引发的 Hanoi 问题 汉诺塔是根据一个传说形成的一个问题。汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着 64 片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 二. 一种数学问题 我们... 阅读详情

       汉诺塔问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着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。

在本文中,将讨论用递归和非递归的方法来解决汉诺塔问题。

1、 通过递归实现汉诺塔问题的求解

设f(n)为将n片圆盘所在塔全部移动到另一塔最少总次数;由递归算法可知:f(1) = 1;当n>1时,f(n)   = f(n-1) +  1 + f(n-1)。f(n) = 把上面n-1片圆盘移动到中间塔最少总次数f(n-1) + 把第n片圆盘移动到目标塔+ 把中间盘的n-1片圆盘移动到目标塔最少总次数为f(n-1)。由数学计算可得:f(n)=2^n-1。(n>0)。此算法的递归代码实现如下所示:

#include <fstream>
#include <iostream>
#include<time.h>
using namespace std;
void Move(int n,char x,char y)
{
   cout<<"把"<<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()
{
  int n;
  cout<<"请输入要求解的汉诺塔的阶数: ";
  cin>>n;
  clock_t start,finish;
  start = clock();
    cout<<"以下是7层汉诺塔的解法:"<<endl;
    Hannoi(n,'a','b','c');
    cout<<"输出完毕!"<<endl;
  finish = clock();
  printf("解决此 %d 阶汉诺塔所需的时间为:%.2f ms\n",n,(double)(finish-start));
  system("pause");
    return 0;
}

2、 通过非递归的思想来实现汉诺塔问题的求解

汉诺塔的非递归算法描述如下:

首先容易证明,当盘子的个数为n时,移动的次数应等于2^n - 1。

一位美国学者发现一种出人意料的方法,只要轮流进行两步操作就可以了。

首先把三根柱子按顺序排成品字型,把所有的圆盘按从大到小的顺序放在柱子A上。

根据圆盘的数量确定柱子的排放顺序:若n为偶数,按顺时针方向依次摆放 A B C;

若n为奇数,按顺时针方向依次摆放 A C B。

(1)按顺时针方向把圆盘1从现在的柱子移动到下一根柱子,即当n为偶数时,若圆盘1在柱子A,则把它移动到B;

若圆盘1在柱子B,则把它移动到C;若圆盘1在柱子C,则把它移动到A。

(2)接着,把另外两根柱子上可以移动的圆盘移动到新的柱子上。

即把非空柱子上的圆盘移动到空柱子上,当两根柱子都非空时,移动较小的圆盘

这一步没有明确规定移动哪个圆盘,你可能以为会有多种可能性,其实不然,可实施的行动是唯一的。

(3)反复进行(1)(2)操作,最后就能按规定完成汉诺塔的移动。

该算法的实现代码如下:

#include <iostream>
#include<time.h>
using namespace std;
//圆盘的个数最多为64
const int MAX = 64;
//用来表示每根柱子的信息
struct st{
     int s[MAX]; //柱子上的圆盘存储情况
     int top; //栈顶,用来最上面的圆盘
     char name; //柱子的名字,可以是A,B,C中的一个
     int Top()//取栈顶元素
     {
           return s[top];
     }
     int Pop()//出栈
     {
           return s[top--];
     }
     void Push(int x)//入栈
     {
           s[++top] = x;
     }
} ;
 
long Pow(int x, int y); //计算x^y
void Creat(st ta[], int n); //给结构数组设置初值
void Hannuota(st ta[], long max); //移动汉诺塔的主要函数
int main(void)
{
     clock_t start,finish;
           int n;
           cout<<"请输入汉诺塔的阶数:";
     cin >> n; //输入圆盘的个数
           start = clock();
     st ta[3]; //三根柱子的信息用结构数组存储
     Creat(ta, n); //给结构数组设置初值
     long max = Pow(2, n) - 1;//动的次数应等于2^n - 1
     Hannuota(ta, max);//移动汉诺塔的主要函数
           finish = clock();
           printf("解决此 %d 阶汉诺塔所需的时间为:%.2f ms\n",n,(double)(finish-start));
     system("pause");
     return 0;
}
void Creat(st ta[], int n)
{
     ta[0].name = 'A';
     ta[0].top = n-1;
    //把所有的圆盘按从大到小的顺序放在柱子A上
     for (int i=0; i<n; i++)
           ta[0].s[i] = n - i;
     //柱子B,C上开始没有没有圆盘
     ta[1].top = ta[2].top = 0;
     for (int i=0; i<n; i++)
           ta[1].s[i] = ta[2].s[i] = 0;
    //若n为偶数,按顺时针方向依次摆放 A B C
     if (n%2 == 0)
     {
           ta[1].name = 'B';
           ta[2].name = 'C';
     }
     else  //若n为奇数,按顺时针方向依次摆放 A C B
     {
           ta[1].name = 'C';
           ta[2].name = 'B';
     }
}
 
long Pow(int x, int y)
{
     long sum = 1;
     for (int i=0; i<y; i++)
           sum *= x;
     return sum;
}
 
void Hannuota(st ta[], long max)
{
  intk = 0; //累计移动的次数
  inti = 0;
  intch;
 while (k < max)
  {
   //按顺时针方向把圆盘1从现在的柱子移动到下一根柱子
   ch = ta[i%3].Pop();
  ta[(i+1)%3].Push(ch);
  cout << ++k << ": " <<
        "Move disk " << ch << " from " <<ta[i%3].name <<
        " to " << ta[(i+1)%3].name << endl;
  i++;
   //把另外两根柱子上可以移动的圆盘移动到新的柱子上
   if(k < max)
  {    
   //把非空柱子上的圆盘移动到空柱子上,当两根柱子都为空时,移动较小的圆盘
   if (ta[(i+1)%3].Top() == 0 ||
       ta[(i-1)%3].Top() > 0 &&
       ta[(i+1)%3].Top() > ta[(i-1)%3].Top())
   {
       ch =  ta[(i-1)%3].Pop();
       ta[(i+1)%3].Push(ch);
       cout << ++k << ": " << "Move disk"
            << ch << " from " << ta[(i-1)%3].name
            << " to " << ta[(i+1)%3].name << endl;
    }
   else
    {
      ch =  ta[(i+1)%3].Pop();
      ta[(i-1)%3].Push(ch);
      cout << ++k << ": " << "Move disk"
           << ch << " from " << ta[(i+1)%3].name
           << " to " << ta[(i-1)%3].name << endl;
    }
 }
}
}


3、 实验结果及分析(测试时以7阶汉诺塔为例)

使用递归算法时运行的情况:


使用非递归算法时运行的情况:


      从实验结果可以看出,与n皇后问题不同,对于汉诺塔问题的求解,当使用递归的方法来解决时它的时间复杂度比非递归的方法要好。而且,使用递归算法写代码时更容易理解。通过对于汉诺塔问题非递归与递归方法的对比可以得出结论:有的时候使用的递归的方法对于问题的求解不仅更能使人容易理解,而且效率更高。我们在以后编代码时也应该注意递归方法的使用。





经典递归算法—汉诺塔问题(含代码示例) 相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如图1)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。 阅读详情

相关推荐

递归经典例题 --- 汉诺塔(图文详解)

保姆级带你了解汉诺塔

Weraphael的博客 1万+

汉诺塔的图解递归算法

汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根...

Rnan_prince的博客 10万+

汉诺塔问题的非递归算法实现

在非递归算法设计中,栈(Stack)和队列(Queue)是最为常见的数据结构。栈是一种后进先出(LIFO, Last In First Out)的数据结构,只能在一端(称为栈顶)进行插入和删除操作。队列是一种先进先出(FIFO, First In First Out)的数据结构,支持在一端添加元素,而在另一端移除元素。对于栈而言,它适用于那些需要回溯或撤销操作的场景,例如表达式求值、浏览器的后退功能等。队列则非常适合处理按顺序排列或处理的任务,如任务调度、打印队列等。

weixin_42513928的博客 1175

汉诺塔问题(递归与非递归)

关于汉诺塔问题的过程分析以及递归非递归两种解法的推理

月巴虫丰博客 4492

保姆级教程:用xmir-patcher一键解锁Redmi AX3000路由器的SSH(附视频演示)

本文提供Redmi AX3000路由器SSH解锁的保姆级教程,详细介绍了使用xmir-patcher工具一键解锁SSH的步骤,包括环境搭建、工具获取、图形化操作详解及常见问题排查。解锁后,用户可通过SSH连接实现刷机、插件安装、网络优化等高级功能,提升路由器性能。

weixin_29216049的博客 729

如何用 Python 实现自动化测试?详细步骤和代码示例

Python自动化测试实战指南 本文系统介绍了使用Python构建自动化测试体系的完整方案。主要内容包括: 环境搭建:Python 3.8+虚拟环境配置,安装pytest、Selenium等核心测试库 分层测试实现: 单元测试:通过计算器示例演示pytest断言和异常测试 API测试:使用requests库进行RESTful接口验证 UI测试:Selenium WebDriver实现网页交互测试 高级特性: 使用fixture管理测试依赖 参数化实现数据驱动测试 生成HTML和Allure测试报告 GitH

m0_64424835的博客 449

汉诺塔问题C语言非递归算法

汉诺塔(Hanoi)问题是学习递归算法时一个很经典的例子,通过递归算法解决,在C站上很多很多,今日就跟着鸡翅一起学习一下非递归算法吧!这次使用的是栈堆的数据结构。//先定义栈元素 int n;//n表示当前是第几个圆盘 char a , b , c;// a,b,c代表三个柱子,a为当前圆盘所在柱子, b为可以借助的柱子, c为目标柱子,即要放到的那个位置的柱子 bool flag;//代表此时圆盘可以移动不 } elem;int top;// top标记栈顶元素 elem e [ 64 ];

一个学习网安的鸡翅 3790

容器内存黑洞排查手册:当PageCache让你的Pod莫名被OOM时

本文深入剖析了容器环境中因Linux内核PageCache机制导致Pod被OOM Killer终止的“内存黑洞”问题。文章解释了Kubernetes基于Working Set内存指标进行OOM判断的逻辑,揭示了传统监控工具与cgroup统计的差异,并通过典型场景分析、实战诊断工具和优化策略,提供了从问题定位到系统调优的完整解决方案。

weixin_29294975的博客 221

c语言汉诺塔递归算法_汉诺塔问题的递归和非递归算法

(给算法爱好者加星标,修炼编程内功)来源:IT修道者https://blog.youkuaiyun.com/computerme/article/details/18080511汉诺塔问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不...

weixin_39926613的博客 1432

openEuler 22.03 LTS SP4离线安装UKUI桌面全攻略(附依赖包下载)

本文提供openEuler 22.03 LTS SP4系统离线安装UKUI桌面环境的完整实战指南。针对无网络环境,详细解析了利用dnf工具下载依赖包、配置离线软件源、处理依赖冲突及安装后优化的全流程,并附带了关键依赖包资源,帮助运维人员高效完成图形化部署。

c7d8e9的博客 478

基于微博API与Scrapy-Redis的城市情绪地图数据爬取实战

本文详细介绍了如何利用Python爬虫技术从微博平台获取用户发布内容,用于构建城市情绪地图的毕业设计项目。文章涵盖了微博API的调用、Scrapy-Redis分布式爬虫架构、数据清洗与存储、反爬虫策略应对以及情绪分析预处理等关键技术,提供了完整的代码实现和实战经验。python复制下载# items.py"""清洗文本数据"""if text:# 移除HTML标签# 移除多余空白字符"""解析微博日期格式"""

2201_76125261的博客 446

汉诺塔问题的递归算法和非递归算法分析

汉诺塔问题的递归算法和非递归算法分析 第一次发博客,想要以此记录自己的学习过程,也方便以后查看复习。希望能坚持下去。 问题描述 相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置n个金盘(依次标号1到n)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,...

笨手笨脚°的博客 6844

educoder实训——计算几何形状的表面积与体积

educoder python实训

qq_41234663的博客 1230

利用问题归约法实现hanoi塔问题_有趣的汉诺塔问题的非递归算法

汉诺塔问题的递归程序很简单,也很容易理解,C源程序如下。// 程序1#include int n;void move(int k, char from, char to) { static int Ser_num; Ser_num++; printf("%3d k=%2d %c-->%c\n",Ser_num,k,from, to); return;}void han...

weixin_32338107的博客 1613

深入解析基于Fluent的蒸发冷凝相变UDF程序及其在重力热管液体蒸发冷凝变化计算中的应用

ANSYS Fluent是一款功能强大的CFD软件,广泛应用于流体流动、传热、化学反应和多相流等领域的数值模拟。Fluent提供了丰富的物理模型和求解器,支持用户自定义函数(UDF)以扩展其功能,实现更为复杂和特定的模拟需求。UDF是用C语言编写的程序,允许用户在Fluent中自定义物理模型、边界条件、源项等,以实现特定的模拟需求。在处理复杂的相变过程、非均匀物性参数或特定的热传导机制时,UDF提供了极大的灵活性和扩展性。

qq_38334677的博客 1265

【系统分析师】高分论文:论基于构件的软件开发(气象灾害影响评估系统)

本文以某手机气象灾害影响评估系统为例,探讨了基于构件技术的软件开发实践。通过分析开发中常见的功能模块重复问题,提出建立企业构件库、针对性选择构件和加强构件管理的解决方案。项目实施中成功复用登录模块等通用构件,并针对气象数据转换需求开发新构件,最终在8个月内高质量完成系统建设。文章总结了构件开发的三个关键点:构件库建设是基础、构件选择需精准、构件管理要规范。同时指出需注意全新需求开发、性能优化等问题,建议通过培训提升团队对构件的理解力。该案例证明构件技术能有效缩短周期、降低成本,为企业积累可复用的技术资产。

数据知道的博客 4253

用非递归算法解决Hanoi汉诺塔问题

开天辟地的神勃拉玛(和中国的盘古差不多的神吧)在一个庙里留下了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,庙里的众僧不倦地把它们一个个地从这根棒搬到另一根棒上,规定可利用中间的一根棒作为帮助,但每次只能搬一个,而且大的不能放在小的上面。计算结果非常恐怖(移动圆片的次数)18446744073709551615,众僧们即便是耗尽毕生精力也不可能完成金

1767

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

非递归汉诺塔算法C语言,汉诺塔问题非递归算法-C

该楼层疑似违规已被系统折叠隐藏此楼查看此楼/*网上看到别人发的关于汉诺塔问题非递归算法,每次都看得有点晕,今天又看了一次,终于明白了其实现原理传统的递归方法效率极其低下,时间和空间复杂度均呈几何级数增长,当问题规模达到20时,计算时间很漫长,更不用谈30以后的了,所以,寻找一种非递归方法就很有必要了。下面是笔者刚刚完成的c++算法*/#include#includeusing namespace...

weixin_28711397的博客 794

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

汉诺塔问题的递归算法和非递归算法

我们定义f ( n ) f(n)f(n)是需要移动的次数;时间复杂度=2^n-1。

m0_62865498的博客 431

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

汉诺塔问题(递归和非递归算法)

#include<stdio.h> void hanoi(int n,char a,char b,char c) { if(n==1)printf("盘号:%d,%c-->%c\n",n,a,b); if(n==2) { printf("盘号:%d,%c-->%c\n",1,a,c); printf("盘号:%d,%c-->%c\n",2,a,b); printf("盘号:%d,%c-->%c\n",1,c,b); }//递归初始条件 if(n&gt

何以琛 558

有趣的汉诺塔问题的非递归算法

汉诺塔问题的递归程序很简单,也很容易理解,C源程序如下。 // 程序1 #include <stdio.h> int n; void move(int k, char from, char to) { static int Ser_num; Ser_num++; printf("%3d k=%2d %c-->%c\n",Ser_num,k,from, to); return; } void hanoi(int k,char from,char pass,char

lhwhit的专栏 421

P123 例6-6 借助堆栈模拟系统的运行时进栈、出栈过程,把汉诺塔问题的递归算法转换为非递归算法,并分析非递归算法的时间复杂度。

P123 例6-6 借助堆栈模拟系统的运行时进栈、出栈过程,把汉诺塔问题的递归算法转换为非递归算法,并分析非递归算法的时间复杂度。 头文件:SeqStack.h #include<stdio.h> #define MaxStackSize 100 typedef struct { int retAddr; int nPara; char fromPegPara; char toPegPara; char auxPegPara; }DataType; typedef struct

AKK188888881的博客 243

汉诺塔问题非递归算法集锦

汉诺塔问题博大精深,我稍微搜集整理了一下,就得到如此多方法,还有好些方法一时不能理解,没有贴出来,请广大网友共同探讨,分享更多更好的方法。

QiaoRuoZhuo的专栏 6656

数据结构:堆栈的应用(汉诺塔问题递归、非递归算法实现)

本文将通过完成以下内容来展示在数据结构中堆栈的应用(汉诺塔问题递归、非递归算法实现),代码解释标注全面而且清晰,代码书写也十分规范,适合初学者进行学习,本篇文章算是本人的一些学习记录分享,希望对有需要的小伙伴提供一些帮助~

m0_63464778的博客 1310

c语言汉诺塔递归算法转非递归,汉诺塔问题非递归算法-C

该楼层疑似违规已被系统折叠隐藏此楼查看此楼/*网上看到别人发的关于汉诺塔问题非递归算法,每次都看得有点晕,今天又看了一次,终于明白了其实现原理传统的递归方法效率极其低下,时间和空间复杂度均呈几何级数增长,当问题规模达到20时,计算时间很漫长,更不用谈30以后的了,所以,寻找一种非递归方法就很有必要了。下面是笔者刚刚完成的c++算法*/#include#includeusing namespace...

weixin_36243739的博客 228

汉诺塔算法的递归与非递归的C以及C++源代码

汉诺塔(又称河内塔)问题其实是印度的一个古老的传说。 开天辟地的神勃拉玛(和中国的盘古差不多的神吧)在一个庙里留下了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,庙里的众僧不倦地把它们一个个地从这根棒搬到另一根棒上,规定可利用

lniwn 2698
上一篇: n皇后问题的三种解法
下一篇: opencv中的meanshift图像分割
IT修道者
IT修道者 领域专家: 人工智能技术领域 领域专家: 人工智能技术领域
博客等级 码龄17年 326粉丝 95原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值