汉诺塔问题(递归算法思想)
  joJp3k0vX7Vq 2023年11月02日 36 0



文章目录

  • 前言
  • 汉诺塔问题的起源:
  • 问题分析:
  • 总结:
  • 代码实现:


前言

  • 🛕“汉诺塔问题”是运用递归思想解决问题的经典例题,非常值得我们去深入地去理解递归的思想!
  • 递归的核心思想就是把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解

汉诺塔问题的起源:

汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。不论白天黑夜,总有一个僧侣在移动这些圆盘,一次只移动一个,小的圆盘必须在大的上面。僧侣们预言,当所有的圆盘都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而庙宇和众生也都将同归于尽……

动态图演示:

汉诺塔问题(递归算法思想)_问题分析

问题分析:

左为A中间为B右为C
1、当柱子上只有一个圆盘时(即n=1),就非常简单,直接从左边(A)移动到右边(C)即可。

汉诺塔问题(递归算法思想)_算法_02


汉诺塔问题(递归算法思想)_算法_03

2、当柱子上有两个圆盘时(即n=2)

  • 第一步先把小圆盘从左(A)移动到中间(B)
  • 第二步再将大圆盘从左(A)移动到右边(C)
  • 第三步将在中间(B)的小圆盘移动到右(C)

汉诺塔问题(递归算法思想)_算法_04


汉诺塔问题(递归算法思想)_算法_05

3、当柱子上有三个圆盘时(即n=3),这个时候如果我们一个一个地去分析,情况就开始变得有点复杂了。

  • 第一步先把上面两个从左(A)先移动到中间(B)(它俩怎样移动先不考虑)
  • 第二步将底下最大的圆盘移动到右边(C
  • 第三步再将中间(B)的两个圆盘移动到右边(C
  • 其中第二步可以直接实现,而第一步和第三步还需继续递归
  • 第一步中在左(A)的两个圆盘通过右(C)移动到中间(B)
  • 第三步中在中间(B)的两个圆盘通过左(A)移动到右(C)
  • 汉诺塔问题(递归算法思想)_算法_06


  • 汉诺塔问题(递归算法思想)_问题分析_07


4、顺着这样的思路

  • 如果柱子上面有n个圆盘,依然可以先把上面的n-1个看作一个整体,通过右(C)移动到中间(B)
  • 把第n个圆盘(最底下的圆盘)移动到右边(C)
  • 然后中间(B)n-1个圆盘又可以把上面的n-2个圆盘继续用递归的思想继续拆分,直到圆盘全部移动到右边(C)

汉诺塔问题(递归算法思想)_c语言_08

总结:

1、第一步移动n-1小盘子从左(A)移动到中间(B)(又可以递归)出第一、二、三步,一直递推,直到左(A)上除了底下那个外,其它全部移动到中间(B)
2、第二步移动第n个小盘子从左(A)移动到右(C)(直接实现)
3、第三步移动n-1小盘子从中间(B)移动到右(C)(又可以递归)出第一、二、三步,一直递推,直到中间(B)上的圆盘全部的圆盘全部移动到右(C),结束!

  • 把n-1个圆盘看作为一个整体,再把n-2个圆盘看作一个整体,再把…,直到达到结束条件!
  • 递归就是要大化小,繁化简
  • 运用递归思想就是让一个函数在它的函数体内调用它自己。
  • 递归会使得函数反复调用自身,每次调用都会在函数栈帧上开辟一块空间,一直递推,直到遇到结束条件。
  • 递归有两个条件,递推关系和结束条件

代码实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

void Hanoi(int n, char A, char B, char C)//将n个圆盘从左边(A)借助中间(B)全部移动到右边(C)
{
	if (n == 1)//当只有1个圆盘时
		printf("%c->%c\n", A, C);//直接将左边(A)的圆盘移动到右边(C)
	else//当n>=2时
	{
		Hanoi(n - 1, A, C, B);//将左边(A)上面的n-1个圆盘借助右边(C)移动到中间(B),
		                      //一直递推,直到左(A)上除了底下那个外,其它全部移动到中间(B)
		                      
		printf("%c->%c\n", A, C);//将左边(A)上剩下的1个圆盘移动到右边(C)
		
		Hanoi(n - 1, B, A, C);//将中间(B)上的n-1个圆盘借助左边(A)移动到右边(C),
		                      //一直递推,直到中间(B)上的圆盘全部的圆盘全部移动到右(C),结束!
	}
}

int main()
{
	int n = 0;
	scanf("%d", &n);//输入n个圆盘
	Hanoi(n, 'A', 'B', 'C');
	return 0;
}


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
joJp3k0vX7Vq