自己学习理解的笔记,欢迎补充。

1.Hanoi塔问题的递归解法

void Hanoi(int n, char a, char b, char c) {if (n == 1) {cout << "从" << a << "移动到" << c << endl;}else {Hanoi(n - 1, a, c, b);Hanoi(1, a, b, c);Hanoi(n - 1, b, a, c);}
}

先简单讲讲主要的思路:1.首先,n个盘子放在A上,我们需要借助C,先移动n-1个盘子给B;2.然后再将A上剩下的最后一个盘子移动到C上;3.最后将B看成是新的A,A是新的B,重复上述12步的操作。

这种实现的方式非常适合用递归来解:实现1和3并不困难,我们只需要将ABC三个字母的排序换一下然后递归调用就可以了;我们要注意的是在每一个2之后程序都会递归调用自身,所以2可以看成是一个递归的终止条件。怎样实现这样的终止条件就是解决问题的关键。

Hanoi(1, a, b, c);

在这一步 Hanoi塔实现了一个“出塔”的操作,它调用自身cout了一句话,实现了将一底部的盘子从A移动到C的过程。让Hanoi(n-1,*,*,*);中的n-1真正减少了1。

注:事实上后来我思考了一下,cout进行的屏幕输出并不重要,重要的是解决问题中间的过程,即abc三者身份进行的互换,以及对n值进行递减的计算方式。

2.Hanoi塔问题的非递归解法

在递归调用的过程中,我们可以发现,下面这一条语句在遇到n-1=1前是不会终止的。在n=1实现之后,函数将返回上一级递归调用,实现接下来的代码内容。

Hanoi(n - 1, a, c, b);

返回上一级调用之后,函数将继续执行下面的两条语句;在这里,函数又进行了第二次递归调用:

Hanoi(n - 1, b, a, c);

也就是说,函数在执行的过程中,对于递归调用会存在至少两种不同的情况,在递归转化为非递归的过程中,我们可以用一个tag进行标识,利用tag不同的值进行判断和执行。

同时,栈具有先进先出的工作特性,这和递归中终止条件完成后返回上一级递归调用的作用是相同的。使用非递归的方式实现该问题,就是要用一个栈来模拟递归的操作,将该问题进行复现。

注:此处参考 PAT乙级 前辈文章 汉诺塔的非递归实现(C语言版)从栈模拟递归(超详细原理讲解)到格雷码式编码改进(效率极高版) ,我差不多是看过一遍之后用他的思路复现了一下。他的文章链接:(前辈讲得非常清楚了!)汉诺塔的非递归实现(C语言版)从栈模拟递归(超详细原理讲解)到格雷码式编码改进(效率极高版)_玮智能的博客-CSDN博客_汉诺塔非递归c语言

typedef struct Block {int n;char a, b, c;int tag;Block(int tn, char ta, char tb, char tc, int ttag) {n = tn;a = ta;b = tb;c = tc;tag = ttag;}//BLOCK的构造函数
}BLOCK;
void Hanoi(int n,char a,char b,char c) {stack<BLOCK> s;BLOCK* temp = new BLOCK(n, a, b, c, 0);s.push(*temp);//进行一个初始化的操作while (s.empty() == 0) {int n = s.top().n;char a = s.top().a;char b = s.top().b;char c = s.top().c;int& tag = s.top().tag;switch (tag) {//用tag来模拟递归:即对于函数语句的读取操作已经进行过多少次case 0://0表示该语句还未被读取过if (n == 1) {cout << "从" << a << "移动到" << c << endl;s.pop();break;}else {tag++;temp = new BLOCK(n - 1, a, c, b,0);s.push(*temp); break;}case 1://可对应递归函数进行函数步骤的理解tag++;temp = new BLOCK(1, a, b, c, 0);s.push(*temp);break;case 2:tag++;temp = new BLOCK(n - 1, b, a, c,0);s.push(*temp);break;case 3://一个关键的操作:因为实际上主函数并不是一个简单的单次递归,而是进行了两次递归,所以倒数第二个数值的情况应该考虑在内s.pop();break;}}
}

对程序进行一些解释:

1.使用栈进行push与pop的操作,可以实现先进先出;利用结构体来保存每次操作的数据,能够实现将动态的过程静态化存储在栈中;

2.函数主体部分使用switch和case语句,是为了模拟递归语句中的递归操作;保存该函数语句进行的状态,0对应刚刚进入该递归语句,开始移动n-1个盘子到过渡柱;1对应第二次进入该递归语句,即将最后一个大盘子移动到C柱上;2对应一次更新,重置n-1时候新的起点柱和过渡柱的操作;

3.应该注意的是,在完成上述三个步骤以后,即tag==3时,这份数据就已经失效了,对应递归函数中的 “}”(即递归程序运行完函数体内部的三条语句之后 结束程序运行) 所以我们应当加一个tag=3的判断条件,并将已经失效的数据释放掉,才能使程序正常运行正常终止。

有问题欢迎留言补充!

C++ Hanoi塔学习笔记(递归与非递归实现)相关推荐

  1. 汉诺塔的改编题(用栈求解,分别递归和非递归)

    限制不能从最左侧的塔直接移动到最右侧,也不能从最右侧直接移动到最左侧,而是必须经过中间,求当塔有N层的时候,打印最优移动过程和最优移动总步数 例如:当塔为两层时,最上层的塔记为1,最下层的塔记为2,则 ...

  2. 【恋上数据结构】递归(函数调用过程、斐波那契数列、上楼梯、汉诺塔、递归转非递归、尾调用)

    递归(Recursion) 什么是递归? 函数的调用过程(栈空间) 函数的递归调用过程 递归实例分析(1 + 2 + 3 + ... + 100 的和) 递归的基本思想.使用套路 斐波那契数列 fib ...

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

    汉诺塔问题的递归算法和非递归算法分析 不想看文字的可以在B站看详细的讲解,点击蓝字->汉诺塔问题的递归和非递归算法 问题描述 相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏.该游戏是 ...

  4. 汉诺塔递归与非递归实现

    汉诺塔递归与非递归实现 背景介绍 汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64 ...

  5. 【学习笔记】求解简单递归式的一般方法

    [学习笔记]求解简单递归式的一般方法 手动博客搬家: 本文发表于20180618 15:53:06, 原地址https://blog.csdn.net/suncongbo/article/detail ...

  6. 转载:二叉树的前中后和层序遍历详细图解(递归和非递归写法)

    二叉树的前中后和层序遍历详细图解(递归和非递归写法) Monster_ii 2018-08-27 17:01:53 50530 收藏 403 分类专栏: 数据结构拾遗 文章标签: 二叉树 前序 中序 ...

  7. C++第七次作业(函数_递归与非递归_多文件)

    文章目录: 一:C++递归与非递归实现整数的阶乘 代码实现 运行结果 二:C++递归与非递归实现Fibonacci数列的计算:a0=1; a1=1; a2=a0+a1; a3=a1+a2; ..... ...

  8. 扫描java类文件_java递归与非递归实现扫描文件夹下文件的实例代码

    java递归与非递归实现扫描文件夹下所有文件 java扫描指定文件夹下面的所有文件,供大家参考,具体内容如下 扫描一个文件夹下面的所有文件,因为文件夹的层数没有限制可能多达几十层几百层,通常会采用两种 ...

  9. C++实现二叉树 前、中、后序遍历(递归与非递归)非递归实现过程最简洁版本

    本文并非我所写,是复制的该链接中的内容: 最近学习二叉树,想编程实现递归和非递归的实现方式: 递归的方式就不说了,因为大家的递归程序都一样:但是对于非递归的实现方式, 根据这几天的查阅资料已看到差不多 ...

最新文章

  1. ASP.NET Core Web Razor Pages系列教程:使用ASP.NET Core创建Razor Pages Web应用程序
  2. 我所理解的OOP——UML六种关系
  3. python类方法和实例方法syntax errors_Python 实例方法,类方法和静态方法
  4. python读取nc文件转成img_使用python的netCDF4库读取.nc文件 和 创建.nc文件[转]
  5. Ext.Net ASP.NET
  6. android opencv 获取小图在大图的坐标_Android开发—基于OpenCV实现相机实时图像识别跟踪...
  7. java cxf_拥抱模块化Java平台:Java 10上的Apache CXF
  8. 前端学习(2447):数据筛选处理
  9. 第二周linux微职位
  10. Nginx服务状态监控
  11. python自动化办公入门书籍-盘点使用Python进行自动化办公所需要的知识点
  12. 【Android进阶】使用Andbase快速开发框架实现常见侧滑栏和滑动标签页组合效果...
  13. grubbs准则 matlab_MATLAB-格拉布斯准则(MATLAB-Grubbs criterion)_0
  14. 索尼手机服务器在哪个文件夹,索尼手机云服务器
  15. gamit添加未知天线
  16. python怎么做计算题_用python做算术题
  17. mt4虚拟服务器账户无效,外汇登录显示无效账户怎么办?
  18. 战略项目——科龙空调中高层干部培训记
  19. 培训班H5宣传单怎么做?快进来拿方案~
  20. springboot设置session超时和session监听

热门文章

  1. 常见图片格式--电子书格式
  2. java 固定长度的集合
  3. 对象的 valueOf 方法
  4. 【spring cloud】(六)消息总线——springcloud Bus
  5. 【腾讯TMQ】穿山甲系列之老司机的千里眼——穿山甲SDK
  6. 校内网黑客入侵案的最新消息,用户日志模块遭挂马“QQ千里眼”
  7. 尺寸压缩与质量压缩的文件大小及效果对比,webp格式
  8. 我说怎么flickr上不去了呢?
  9. RenderDoc[01] 使用RenderDoc 分析Android游戏(免Root)
  10. 【Rhapsody学习笔记】3:Dishwasher