【C语言】函数递归:汉诺塔问题

这篇具有很好参考价值的文章主要介绍了【C语言】函数递归:汉诺塔问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

汉诺塔问题是一道经典的计算机科学中的递归算法题,通过解决汉诺塔问题以更好的理解递归。

函数递归

函数递归:函数自己调用自己。

函数递归的两个必要条件:
1.函数自身的调用要有限制条件,如果没有限制条件,就会无限的自己调用自己而导致栈溢出(stack overflow)(关于栈溢出的问题我会再出一篇文章详细分析底层)。
2.函数每一次调用自己时,要逐渐接近限制条件。

函数递归的本质:大事化小。把一个大问题分解成若干个小问题。

什么是汉诺塔问题?

问题的描述如下:

有三根柱子,标记为A、B、C,A柱子上有n个大小不同的盘子,盘子从下到上按照大小递增排列。现在需要将A柱子上的所有盘子移动到C柱子上,移动过程中可以借助B柱子,但是每次只能移动一个盘子,并且大盘子不能放在小盘子上面

起始状态:
利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记
目标状态:
利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记
移动过程中的违规状态(大盘子在小盘子上面):
利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记

题目

请用C语言实现以下功能:输入在A柱子上的盘子数,输出所有盘子从A柱子移动到C柱子的整个过程

解题思路

只要把解题思路搞明白了,无论用什么编程语言,都只是一种思路的不同表示形式而已。

1. 移两个盘子

先从最简单的移两个盘子开始分析:
利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记
两个盘子从A柱移到C柱的过程:

  1. 小盘子先从A柱移到B柱
  2. 然后大盘子从A柱移到C柱
  3. 最后小盘子从B柱移到C柱。

过程简写如下:

  1. A–>B
  2. A–>C
  3. B–>C

要想让A柱最底下最大的盘子移到C柱上,只有上面的小盘子移到B柱时,大盘子才能从A柱移到C柱。

2. 移n个盘子

知道怎么移两个盘子之后再看移n个盘子:
利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记
移两个盘子和移n个盘子的相同之处:

无论A柱有多少个盘子,想要让A柱最底下最大的盘子移到C柱上,只有这大盘子上面所有的小盘子都移到B柱时,最下面的大盘子才能从A柱移到C柱。
所以我们可以先把上面的n-1个盘子看成一个整体,把这个整体从A柱移到B柱,再把最下面的盘子从A柱移到C柱。利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记
步骤1.把前n-1个盘子组成的整体从A柱移到B柱
利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记

步骤2.再把最下面的盘子从A柱移到C柱
利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记
步骤3.把前n-1个盘子组成的整体从B柱移到C柱
利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记
在不考虑怎么移前n-1个盘子的情况下,上面的这三个步骤和移两个盘子的步骤简直一模一样!

那具体怎么移动上面的n-1个盘子呢?

以步骤3中为例:把前n-1个盘子组成的整体从B柱移到C柱的过程中,这个整体又可以划分为前n-2个盘子组成的整体和第n-1个盘子
利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记
想要把第n-1个盘子从B柱移到C柱,得先把上面的前n-2个盘子看成一个整体,这个整体从B柱移到A柱。
利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记
发现了吗?我已经正在把一个大问题拆分成若干个小问题了:
刚开始的大问题是在A柱上面的n个盘子从A柱移到C柱,在上面的 步骤1步骤3 中,又可以细分成一些小问题:把n-1个盘子从A柱和B柱,把n-1个盘子从B柱和C柱这些。当然,在移动n-1个盘子的过程中会出现更小的问题。这些无数的小问题们直到遇见 步骤2 的时候,也就是只有一个盘子的时候,不再需要再划分成更小的问题解决,直接移动这1个盘子即可。可能这个时候思路还比较乱,接下来我会在下面一节的抽象中展现完整的思路。

3.抽象

利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记
这里可能会有几个疑问:

  1. 每一次从一个柱子移到另一个柱子中,这两个柱子的位置不是固定的,怎么处理这些柱子的对应关系?
  2. 什么时候不会再划分出两个新的函数,也就是说限制条件是什么?

第一个问题回答:我们不能全部知道各种情况什么柱要移到什么柱,但是他们有共同的特点:都是从起始的柱子移到目的地柱子,总有一个柱子是第三者当工具。我们可以称起始的柱子为起始柱,称目的地柱子为目标柱,称第三者为工具柱

A柱,B柱,C柱是固定的,但是他们每次充当的角色可以是不同的 (起始柱,目标柱,工具柱)

第二个问题回答:当n减到1时,也就是只有一个盘子时,按照上面的3个步骤走一遍,发现只需走第二个步骤,因为第一个和第三个步骤是0个盘子从起始柱移到目标柱,没有盘子了就肯定不要执行啦。

所以限制条件是n>0

综上所述:
解决汉诺塔问题的函数需要用到4个变量:

  1. 盘子的个数n
  2. 起始柱
  3. 目标柱
  4. 工具柱

有了步骤,参数还有限制条件,代码的实现就轻松很多了。

代码实现

#include<stdio.h>

//        盘子个数  起始柱  目标柱  工具柱
void hanoi(int n, char A, char C, char B)
{
	if (n > 0)//限制条件
	{
		//第一步,把A柱上面的n-1个盘子移到B柱。此时A柱为起始柱,B柱为目标柱,C柱为工具柱
		hanoi(n - 1, A, B ,C);

		//第二步,直接输出A柱最底下最大的盘子移到C柱的过程。此时A柱为起始柱,C柱为目标柱
		printf("%c-->%c\n", A, C);

		//第三步,把B柱上面的n-1个盘子移到C柱。此时B柱为起始柱,C柱为目标柱,A柱为工具柱
		hanoi(n - 1, B, C, A);
	}
}


int main()
{
	int n = 0;
	printf("请输入在A柱上的盘子的个数:>");
	scanf("%d", &n);
	char A = 'A';
	char B = 'B';
	char C = 'C';
	hanoi(n,A,C,B);
	return 0;
}

代码运行例子:
把3赋值给变量n:
利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记

把4赋值给变量n:
利用递归函数调用解决移动10个盘子的汉诺塔问题,c语言,算法,笔记

结语

非常感谢您能够阅读完这篇文章,如果有任何建议或纠正欢迎在评论区留言。如果您认为这篇文章对您有所收获,点一个小小的赞就是我创作的巨大动力,谢谢!文章来源地址https://www.toymoban.com/news/detail-769560.html

到了这里,关于【C语言】函数递归:汉诺塔问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 递归求解汉诺塔问题(超详解)

    这个问题是关于三根柱子和一些圆盘的游戏。 初始时,所有的圆盘按照从大到小的顺序叠放在一根柱子上,目标是将所有圆盘从起始柱子移动到目标柱子上,在移动过程中,要满足以下规则喵: 每次只能移动一个圆盘。 大圆盘不能放在小圆盘上。 只能通过中间柱子作为辅

    2024年02月15日
    浏览(77)
  • C语言实现汉诺塔详细步骤(递归与非递归)及代码

    C语言汉诺塔问题是一个经典的问题,在学习编程的初学者中非常流行。它涉及到了递归的思想,能够帮助我们理解递归的基本原理。 首先,我们来了解一下汉诺塔的问题。汉诺塔问题是指:有三根柱子A,B,C,A柱子上有n个盘子,盘子大小不等,且从下到上由小到大排列,现在

    2023年04月08日
    浏览(40)
  • C++实现汉诺塔问题(递归实例)

    汉诺塔的由来 法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。 印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论

    2024年02月07日
    浏览(36)
  • C语言有关“函数用于调用的参数太少”问题解决办法

    🦄 个人主页 :修修修也 🎏 所属专栏 :程序调试及报错解决 ⚙️ 操作环境 : Visual Studio 2022 我们在使用C语言编写程序,特别是使用 函数递归 时经常会遇到编译器报错“ 用于调用的参数太少/太多 ”,如图: 那么遇到这种情况我们该如何解决呢? 首先以下面一段代码为例向

    2023年04月08日
    浏览(36)
  • 递归——汉诺塔问题(结合代码理解,终于懂了)

    问题 汉诺塔问题是一个经典的递归问题,汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子, 在一根柱子上从下往上按照大小顺序摞着 64 片圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一 根柱

    2024年02月04日
    浏览(41)
  • Py:代码性能分析之使用python工具—如利用cProfile【输出每个函数的运行时间和调用次数】/line_profiler【输出每行代码的执行时间】)同时对比斐波那契数列问题的递归方法和动态规划

    Py:代码性能分析之使用python工具—如利用cProfile【输出每个函数的运行时间和调用次数】/line_profiler【输出每行代码的执行时间】)同时对比斐波那契数列问题的递归方法和动态规划算法实现 目录

    2024年02月04日
    浏览(81)
  • 递归详解,斐波那契数列、二叉树遍历、汉诺塔问题的递归代码

    一、递归详解 [1] 递归是一种编程技巧,通过函数调用自身来解决问题。递归中包含三个要素:递归定义、递归出口和递归调用。 [2] 递归定义指的是问题可以被分解为同类且更小规模的子问题。在递归过程中,问题会不断被分解为规模更小的子问题,直到达到一个基本情况,

    2024年02月08日
    浏览(40)
  • 斐波那契数列、青蛙跳台阶、汉诺塔(C语言Java通用)、递归练习题

    Write once,Runanywhere. 🔥🔥🔥 本派文章详细斐波那契数列、青蛙跳台阶、汉诺塔(C语言Java通用)、递归练习题。 💥 💥 💥 如果你觉得我的文章有帮助到你,还请【关注➕点赞➕收藏】,得到你们支持就是我最大的动力!!! 💥 💥 💥 ⚡ 版权声明:本文由【马上回来了】原创、

    2023年04月08日
    浏览(67)
  • 【C语言】——函数递归,用递归简化并实现复杂问题

    不多废话了,直接开始。 递归是学习C语言函数绕不开的⼀个话题,那什么是递归呢? 递归其实是⼀种解决问题的方法,在C语言中,递归就是函数调用自己。 写⼀个史上最简单的C语言递归代码: 上述就是一个简单的递归程序,只不过上面的递归只是为了演示递归的基本形式

    2024年02月05日
    浏览(41)
  • 【C语言】——递归函数,用递归简化并实现复杂问题

    不多废话了,直接开始。 递归是学习C语言函数绕不开的⼀个话题,那什么是递归呢? 递归其实是⼀种解决问题的方法,在C语言中,递归就是函数调用自己。 写⼀个史上最简单的C语言递归代码: 上述就是一个简单的递归程序,只不过上面的递归只是为了演示递归的基本形式

    2024年02月03日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包