递归,从代码实现上来看就是函数的自我调用,即在函数体中再调用函数本身。如:

void dg(int i){if(i>10)return;//递归出口cout<<i;//可以是其他语句,这里是为了显示递归过程dg(i+1);
}

可见,在dg函数中,调用了一次dg函数。细心的人可能会注意到为什么在函数体中有一个条件判断。这不难理解,倘若没有设置这个出口,该函数就会不断地进行自我调用,相当于一个链条不停向下延申,没有尽头。这对于函数的递归而言,只有”递“,而没有了”归“。

在得知了递归是如何实现之后,我们再从图形的方向来进一步看看什么是递归。

递归,见字知意,先递出去,后回归。我们可以将递归的过程看作一个树状图。从树冠开始从上往下延申,称为“递”,而从最底下的树叶从下往上上升,称为“归”,如图1,图中数字表示递归顺序。

这时或许会有疑惑,递归不是说是树状图吗?图1中分明是链状。不急,往下看。

图1中之所以没有分叉,是因为上面的函数体中只有一个函数的自我调用(函数体中只有一个dg函数被执行)。倘若我们在函数体中在加上一个dg函数,如下:

void dg(int i){if(i>10)return;//递归出口cout<<i;//可以是其他语句,这里是为了显示递归过程dg(i+1);cout<<"回归执行";dg(i+1);
}

那么这时递归的过程图便成为了上述的树状图,如图2,其中数字表示递归顺序。

这里我们可以通过树状图来分析一下代码,箭头1、2、4、7、8、10时执行了“cout<<i”,箭头4、7、10时执行了“cout<<"回归执行"”,而在树叶(即没有分叉的末端,如图2中有四个树叶)处执行了if语句返回上一级。

接下来,趁热打铁,用一道经典递归题三阶汉诺塔来加深对这个过程的理解:

汉诺塔问题可以这样描述:假设有A、B、C三个木桩和n个大小均不相同的盘子(Disc,或圆盘),从小到大编号为1,2,3,...,n,编号越大直径越大。开始的时候,n个盘子都套在A木桩上,现在希望能找到将A木桩上的盘子借着B木桩当中间桥梁,全部移到C木桩上最少次数的方法。不过在搬动时还必须遵守下列规则:

(1)直径较小的盘子永远只能置于直径较大的盘子上。

(2)盘子可以任意地从任何一个木桩移到其他的木桩上。

(3)每一次只能移动一个盘子,而且只能从最上面的盘子开始移动。

这里我们列举n=1~4时盘子的移动路径及移动次数

:该题所说的移动路径默认最短移动路径。

n=1时,1->3,移动了2^1-1次

n=2时,1->2,1->3,2->3,移动了2^2-1次

n=3时,1->3,1->2,3->2,1->3,2->1,2->3,1->3,移动了2^3-1次

n=4时,1->2,1->3,2->3,1->2,3->1,3->2,1->2,1->3,2->3,2->1,3->1,2->3,1->2,1->3,2->3,移动了2^4-1次

除此以外,再通过一些列举我们发现,对于奇数个盘子第一步总是1->3,而偶数个盘子第一步总是1->2,并且,对于奇数个盘子的移动路径,2n-1个盘子的移动路径总是包含在2n+1个盘子的移动路径中;对于偶数个盘子的移动路径,2n个盘子的移动路径总是包含在2n+2个盘子的移动路径。

仅仅通过以上说法并不能帮助我们解题,但可以为我们引导出一个递归的思路,那么,进一步思考归纳,我们可以得出以下三个步骤:

1.先将n-1个盘子从木桩1借助木桩3移动到木桩2;

2.随后将第n盘子(即最大的盘子)从木桩1移动到木桩3;

3.将n-1个盘子从木桩2移动到木桩3。

仔细看可以发现第三步又回归到前面两步(n-1个盘子时,我们只要将n-2个盘子从木桩2借助木桩3移动到木桩1,再将第n-1个盘子(即最大的盘子)移动到木桩3),形成了一个循环传递,而出口无疑是当盘子数量为1时;

根据上述,我们可以考虑设计一个递归函数来解决该问题。

显示其过程的代码如下:

void hanoi(int n, int p1, int p2, int p3) {if (n == 1)cout << p1 << "->" << p3 << endl;//递归出口else {hanoi(n - 1, p1, p3, p2);cout << p1 << "->" << p3 << endl;hanoi(n - 1, p2, p1, p3);}
}

利用堆栈求解如下:

void hanoi(int n, vector<int>& A, vector<int>& B, vector<int>& C){if (n == 1){   //这既是出口,也是第一步C.push_back(A.back());A.pop_back();}else{hanoi(n-1, A, C, B);    // 将木桩A上面n-1个盘子借助木桩C移动到木桩BC.push_back(A.back());  // 将木桩A最后一个盘子移到木桩CA.pop_back();          // 木桩A上最后一个盘子被移走,木桩A空了hanoi(n-1, B, A, C);     // 将木桩B上面n-1个盘子通过空的木桩A移到木桩C}
}

其递归过程图可参照图2。

详解递归,文+图+代码,带你轻松了解递归算法的设计思路(附汉诺塔分析及题解)相关推荐

  1. 【C递归和迭代】兔子繁殖问题、青蛙跳台阶问题和汉诺塔问题

    ⭐博客主页:️CS semi主页 ⭐欢迎关注:点赞收藏+留言 ⭐系列专栏:C语言初阶 ⭐代码仓库:C Advanced 家人们更新不易,你们的点赞和关注对我而言十分重要,友友们麻烦多多点赞+关注,你们 ...

  2. 递归算法(python),汉诺塔问题,斐波那契数列,一个简单的递归实例,用递归实现阶乘,用递归查看目录及文件

    https://blog.csdn.net/hanhanwanghaha宝藏女孩 欢迎您的关注! 欢迎关注微信公众号:宝藏女孩的成长日记 让这个可爱的宝藏女孩在努力的道路上与你一起同行! 如有转载,请 ...

  3. python面向过程实践汉诺塔_递归汉诺塔-和递归汉诺塔相关的内容-阿里云开发者社区...

    多柱汉诺塔最优算法设计探究 多柱汉诺塔最优算法设计探究 引言 汉诺塔算法一直是算法设计科目的最具代表性的研究问题,本文关注于如何设计多柱汉诺塔最优算法的探究.最简单的汉诺塔是三个柱子(A.B.C),因 ...

  4. 算法 - 递归实现汉诺塔(The Tower of Hanoi)

    目录 引言: 分析: 分析两片汉诺塔的迁移过程: 分析三片汉诺塔的迁移过程: 代码实现: 递归出口: 递归过程: 完整程序代码: 运行结果: 参考资料:​​​​​ 引言: 今天接触到了一个非常有意思的 ...

  5. 汉诺塔的递归实现,看完就懂了

    对于要实现汉诺塔递归程序的同学,我相信有一部分同学还没有真正的玩过汉诺塔这个游戏,我建议先在手机应用商店下载一个汉诺塔游戏去感受一下,当了解了游戏的玩法之后,也更方便你去理解递归代码的逻辑. 下面通过 ...

  6. 图解汉诺塔(满屏幕都是图)

    图解汉诺塔(满屏幕都是图) 汉诺塔问题 步骤1: 步骤2 步骤3: 技术总结 和很多人一样,我刚刚接触汉诺塔的时候,可能说是头晕目眩,立马放弃. 但如果用图形表示感觉会好很多. 以下是我的学习思路: ...

  7. C语言:汉诺塔(经典递归问题)

    汉诺塔问题介绍 关于汉诺塔的传说: 法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针.印度教的主神梵天在创造世界的时候,在其中一 ...

  8. 青蛙跳台(含变种)及汉诺塔递归,母牛生小牛

    青蛙跳台(含变种)及汉诺塔递归,母牛生小牛 文章目录 青蛙跳台(含变种)及汉诺塔递归,母牛生小牛 #define _CRT_SECURE_NO_WARNINGS #include<Windows ...

  9. 递归法:汉诺塔(快速掌握)

    汉诺塔分析:转换柱子的角色,和辅助柱子 发现从递归角度:将1-N与2-N移动到B之后,在C不动的情况下,并不是同一个等价形式:经过转化之后:以下形式与原来的1-N等价 把1-N-1移动到C,N移动到B ...

最新文章

  1. 以Attention Model为例谈谈两种研究创新模式
  2. C语言-数据数据类型、变量与常量
  3. SERV-U FTP SERVER和SERV-U MFT SERVER的区别
  4. 【转】ABAP的坑3
  5. 节省大量教科书的三种潜在风险方法
  6. 服务器打包运营级H5商城源码
  7. docker中的mysql操作
  8. 第一次HACK别人的DLL
  9. 《机器学习实战》程序清单4-2 朴素贝叶斯分类器训练函数
  10. 方舟服务器端口协议,《方舟:生存进化》正版开服端口映射教程及后台命令一览...
  11. 为何python不好找工作-谁说Python找工作难?人生苦短,Python工程师你们还好吗?...
  12. 重新组织和重新生成索引sp_RefreshIndex
  13. 实现栈的基本操作(c语言)
  14. 计算机信息管理学书心得,学习erp的心得体会共计5篇
  15. 软件工程课程设计小组人员分工
  16. linux中安装openoffice
  17. OpenCV旋转矩形RotatedRect的Points函数遇到的问题
  18. 服务器光纤信号灯,光纤收发器的六个指示灯都代表什么?
  19. verilog specify语法
  20. 移位运算符(<<、>>和>>>)

热门文章

  1. python怎么实现deepcopy_python深度复制字典,copy方法与deepcopy方法
  2. [DP] bzoj2423: [HAOI2010]最长公共子序列
  3. Redis-06-key操作
  4. 河南电视台:让中原文化“云”中起舞
  5. Linux基础知识5:通配符、进程管理、命令替换符、转义符、shell元字符、ascii码对照表
  6. win10下安装oracle11g教程
  7. 【华人学者风采】蒋旭宪 360
  8. 关于Google Wallet的使用
  9. 7-5-1 map 统计英文单词个数
  10. [文档Ver 1.0]机顶盒死机监控,频道锁定,发送短信