C#汉诺塔递归算法实现
目录:
一、什么是递归
方法调用自己的行为就是递归,递归必须要有终止条件,不然它会无限递归。
1.先来看一下一个递归的例子
此程序的Fact方法从大到小地一级一级地调用自己,直到参数为1,然后就开始返回一级一级的从小到大地累乘,然后就计算出number的阶乘了。
static int Fact(int num)
{
if (num <= 1)
{
return num;
}
else
{
return num * Fact(num - 1);//调用自己,这一步是关键
}
}
2.递归的基本原理
以下是《C#图解教程》对于递归的描述:
- 除了调用其他方法,方法也可以调用自身,这叫做递归。
- 调用方法自身的机制和调用其他方法其实是完全一样的,都是为每一次方法调用把新的栈帧压入栈顶。
我个人认为递归就是把你要干的事情抽象一个成可以有限步数解决的方法,然后某一步解决不了就再调用这个方法,直到可以解决(结束递归的条件)这个问题就返回。
下面再看一个具体的例子来了解递归。
二、汉诺塔问题
1.汉诺塔的故事
汉诺塔由法国数学家爱德华·卢卡斯创造,他曾经编写了一个印度的古老传说:
在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。
2.回到编程,汉诺塔问题主要就是解决这个问题:
有A、B、C三根针,A上从小到大放着n层盘子,要从A上所有的盘子移动到C盘上。
条件是一次只能移动一个盘子,无论什么时候小盘子必须在大盘子上面。
汉诺塔问题求的是把盘子从A移到C总共的移动次数是多少。
这是我之前追踪4层汉诺塔运行步骤画的笔记
事实证明,没多大帮助。
要想理解递归必须要放弃理解递归,放弃跟踪全程步骤。
解决问题是计算机的事,你只要明确要把每一步怎么传给计算机,递归两层之间怎么交接,以及递归结束的条件就可以。
3.怎么解决汉诺塔问题
要解决汉诺塔问题就要用到递归思想,这里拿四层汉诺塔举例子:
要完成四层汉诺塔,需要先把第四层盘子从A柱放到C柱,而要把第四层盘子放到C柱,就要把上面三层的盘子放到B柱:
那么要把这三层盘子移到B柱,那么就要先把第三层盘子移到B柱。
要把第三层盘子移到B柱,就要把第二层盘子移到C柱子。
要把第二层盘子移到C柱,就要把第一层盘子移到B柱子。
移动一层汉诺塔到另一个柱不简单吗?
这样子把问题解决了,第四层盘子就可以移动到C柱上了。
然后把剩下的三层汉诺塔也按照上面的思想,就可以移动到C柱上了。
4.具体代码实现
把大象装进冰箱需要多少步
- 把冰箱门打开
- 把大象放进去
- 把冰箱门关上
把汉诺塔放到C柱需要多少步
- 把底层上面的盘子放到B柱
- 把最底层盘子放到C柱
- 把B柱那些盘子放到C柱
抽象一下就是:
- 把n-1层盘子从起点移到暂存区
- 然后把第n层盘子从起点移到终点
- 然后把n-1层盘子从暂存区移到终点
在这里可以创建一个Move方法来移动盘子
static void Move(int pile, char src, char tmp, char dst)
{
}
src就是源起点,tmp就是暂存区,dst就是终点
最外层的Move方法完成的是把pile层汉诺塔从src经过tmp移动到dst
现在要把大象装进冰箱了
在Move方法里面调用Move方法来解决之后的问题:
1. 把冰箱门打开
Move(pile - 1, src, dst, tmp);
这层Move完成的是把pile-1层汉诺塔从src经过dst移动到tmp
2.把大象塞进去
Move(1, src, tmp, dst);
这层Move完成的是把最底层汉诺塔盘子从src直接移动到dst
3.把门关上
Move(pile - 1, tmp, src, dst);
这层Move完成的是把pile-1层汉诺塔从tmp经过src移动到dst
Move方法完整代码:
static void Move(int pile, char src, char tmp, char dst)
{
if (pile == 1)//pile=1问题就好解决了
{
Console.WriteLine($"{src} --> {dst}");
steps++;
return;
}
Move(pile - 1, src, dst, tmp);
Move(1, src, tmp, dst);
Move(pile - 1, tmp, src, dst);
}
每一层Move方法都有他自己的起点、暂存区和终点,我们只需要把上一层的起点、暂存区和终点传过去就行了。
5. 完整代码
以下是完整代码:
using System;
namespace Hanoi
{
class Program
{
public const int MAX_VALUE = 30;//声明最大值常量
public static int steps = 0;
static void Main(string[] args)
{
int levels = 0;
Console.Write($"输入汉诺塔层数(1~{MAX_VALUE}): ");
levels = int.Parse(Console.ReadLine());
if (levels > 0 && levels < MAX_VALUE)
{
Move(levels, 'A', 'B', 'C');
Console.WriteLine($"一共移动了{Program.steps}次。");
Console.ReadKey();
return;
}
Console.WriteLine("输入范围错误");
Console.ReadKey();
}
static void Move(int pile, char src, char tmp, char dst)
{
if (pile == 1)//pile=1问题就好解决了
{
Console.WriteLine($"{src} --> {dst}");
steps++;
return;
}
Move(pile - 1, src, dst, tmp);
Move(1, src, tmp, dst);
Move(pile - 1, tmp, src, dst);
}
}
}
运行结果如下:
C#汉诺塔递归算法实现的更多相关文章
- C语言之算法初步(汉诺塔--递归算法)
个人觉得汉诺塔这个递归算法比电子老鼠的难了一些,不过一旦理解了也还是可以的,其实网上也有很多代码,可以直接参考.记得大一开始时就做过汉诺塔的习题,但是那时代码写得很长很长,也是不理解递归的结果.现在想 ...
- python的递归算法学习(3):汉诺塔递归算法
汉诺塔问题是递归函数的经典应用,它来自一个古老传说:在世界刚被创建的时候有一座钻石宝塔A,其上有64个金蝶.所有碟子按从大到小的次序从塔底堆放至塔顶.紧挨着这座塔有另外两个钻石宝塔B和C.从世界创始之 ...
- 题目1458:汉诺塔III(不一样的汉诺塔递归算法)
题目链接:http://ac.jobdu.com/problem.php?pid=1458 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...
- C语言数据结构----递归的应用(斐波拉契数列、汉诺塔、strlen的递归算法)
本节主要说了递归的设计和算法实现,以及递归的基本例程斐波拉契数列.strlen的递归解法.汉诺塔和全排列递归算法. 一.递归的设计和实现 1.递归从实质上是一种数学的解决问题的思维,是一种分而治之的思 ...
- 运用Turtle实现汉诺塔的可视化运行(递归算法)
运用Turtle实现汉诺塔的可视化运行(递归算法) 汉诺塔问题又名河内塔问题,是源于印度一个古老传说的益智玩具.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆 ...
- 汉诺塔问题(The Tower of Hanoi)的递归算法与非递归算法
非递归算法: 根据圆盘的数量确定柱子的排放顺序: 若n为偶数,按顺时针方向依次摆放 A B C: 若n为奇数,按顺时针方向依次摆放 A C B. 然后进行如下操作: (1)按顺时针方向把圆盘1从现在的 ...
- 理解 Hanoi 汉诺塔非递归算法
汉诺塔介绍: 汉诺塔(港台:河内塔)是根据一个传说形成的数学问题: 最早发明这个问题的人是法国数学家爱德华·卢卡斯. 传说越南河内某间寺院有三根银棒,上串 64 个金盘.寺院里的僧侣依照一个古老的预言 ...
- Java递归算法——汉诺塔问题
//================================================= // File Name : Tower_demo //-------------------- ...
- 汉诺塔问题(Hanoi Tower)递归算法解析(Python实现)
汉诺塔问题 1.问题来源:汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从上往下从小到大顺序摞着64片黄金圆盘.上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根 ...
- Python汉诺塔问题递归算法与程序
汉诺塔问题: 问题来源:汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从上往下从小到大顺序摞着64片黄金圆盘.上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱 ...
随机推荐
- 聊聊wireshark的进阶使用功能
1. 前言 emmm,说起网络知识学习肯定离不来wireshark工具,这个工具能够帮助我们快速地定位网络问题以及帮助正在学习网络协议这块的知识的同学验证理论与实际的一大利器,平时更多的只是停留在初步 ...
- 如何配置.h头文件include“”相对路径
编译工程时,找的是当前main.c文件下的.h文件,如果当前路径下没有就会报错,当前路径用.\表示,上一级目录用..\表示. 如果你的main.h文件在main.c的上一级目录中Include 文件夹 ...
- ERP 财务管理的应付帐款流程
导读:应付帐款流程与应收帐款流程是财务管理的开端,也是财务工作的主要流程.若能够这两大流程控制好了,ERP系统的财务模块也就成功了一大半了.我先讲一下财务管理的应付帐款流程. 企业的应付帐款有很多种类 ...
- fmpeg 多张图片转视频,视频转gif,截取视频,截取视频里的帧
ffmpeg 多张图片转视频,视频转gif,截取视频,截取视频里的帧 月色下的独轮车 于 2017-06-20 17:32:01 发布 6250 收藏 3文章标签: ffmpeg版权 android学 ...
- Unexpected keys "@@dva", "user" found in preloadedState argument passed to createStore. Expected to find one of the known reducer keys instead: "router", "loading". Unexpected keys will be ignored.
Please use `require("history").DOMUtils` instead of `require("history/DOMUtils") ...
- bootstrap响应式原理
Bootstrap 框架的网格系统工作原理如下:1 .数据行 (.row) 必须包含在容器( .container )中,以便为其赋予合适的对齐方式和内距 (padding) . 如: <div ...
- Acwing76场周赛
题目链接 这次还是只做出来两道题,前两题都挺简单的,注意第二题需要开long long不开会wa,代码粘上来,以后可能会看吧 第一题 #include<iostream> #include ...
- P8368 [LNOI2022] 串 题解
题目链接 题目分析 题目要求我们构造一个最长的 \(T\) 序列,我们首先从每个 \(T_i\) 入手,思考如何安排才能合法. 容易观察到对于每个 \(T_i\),合法的 \(T_{i-1}\) 有两 ...
- 【scipy 基础】--聚类
物以类聚,聚类算法使用最优化的算法来计算数据点之间的距离,并将它们分组到最近的簇中. Scipy的聚类模块中,进一步分为两个聚类子模块: vq(vector quantization):提供了一种基于 ...
- vivo 网络端口安全建设技术实践
作者:vivo 互联网安全团队 - Peng Qiankun 随着互联网业务的快速发展,网络攻击的频率和威胁性也在不断增加,端口是应用通信中的门户,它是数据进出应用的必经之路,因此端口安全也逐渐成为了 ...