C#利用递归算法解决汉诺塔问题

目录
  • 一、什么是递归
  • 二、汉诺塔问题
    • 1.汉诺塔的故事
    • 2.解决思路
    • 3.怎么解决汉诺塔问题
    • 4.具体代码实现
  • 三、完整代码

一、什么是递归

方法调用自己的行为就是递归,递归必须要有终止条件,不然它会无限递归。

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方法都有他自己的起点、暂存区和终点,我们只需要把上一层的起点、暂存区和终点传过去就行了。

三、完整代码

以下是完整代码:

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#汉诺塔递归算法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C# 递归算法详解

    目录 1)1.1.2.3.5.8.......用递归算法求第30位数的值? 2)编写计算斐波那契(Fibonacci)数列的第n项函数fib(n)斐波那契数列为:0.1.1.2.3.--, 3)求1+2+3+4+5+....+n的值 4)有两个整数型数组,从小到大排列,编写一个算法将其合并到一个数组中,并从小到大排列 总结 1)1.1.2.3.5.8.......用递归算法求第30位数的值? 首先我们能够发现从第3位数起后一位数等于前两位数值之和,即:x=(x-1)+(x-2),x>2; 这里须

  • c#汉诺塔的递归算法与解析

    从左到右 A  B  C 柱 大盘子在下, 小盘子在上, 借助B柱将所有盘子从A柱移动到C柱, 期间只有一个原则: 大盘子只能在小盘子的下面. 如果有3个盘子, 大中小号, 越小的越在上面, 从上面给盘子按顺序编号 1(小),2(中),3(大), 后面的原理解析引用这里的编号. 小时候玩过这个游戏, 基本上玩到第7个,第8个就很没有耐心玩了,并且操作的动作都几乎相同觉得无聊.  后来学习编程, 认识到递归, 用递归解决汉诺塔的算法也是我除了简单的排序算法后学习到的第一种算法. 至于递归,简单来说

  • c#实现汉诺塔问题示例

    汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具.下面是c#实现汉诺塔示例 复制代码 代码如下: using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace 汉诺塔{    class Program    {        static void hanoi(char A, char B, char C, int count)        {     

  • C#实现递归算法经典实例

    目录 一 .递归算法简介 二 .Fibonacci数列和阶乘 1.Fibonacci数列 2.阶乘 三 .汉诺塔问题 四 .排列组合 1.输出任意个数字母.数字的全排列 2.将全排列结果保存到链表中 总结 一 .递归算法简介 在数学与计算机科学中,递归是指在函数的定义中使用函数自身的方法. 递归算法是一种直接或者间接地调用自身算法的过程.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解. 递归算法解决问题的特点: (1) 递归就是在过程或函数里调用自身

  • C#利用递归算法解决汉诺塔问题

    目录 一.什么是递归 二.汉诺塔问题 1.汉诺塔的故事 2.解决思路 3.怎么解决汉诺塔问题 4.具体代码实现 三.完整代码 一.什么是递归 方法调用自己的行为就是递归,递归必须要有终止条件,不然它会无限递归. 1.先来看一下一个递归的例子 此程序的Fact方法从大到小地一级一级地调用自己,直到参数为1,然后就开始返回一级一级的从小到大地累乘,然后就计算出number的阶乘了. static int Fact(int num) { if (num <= 1) { return num; } el

  • C++基于递归算法解决汉诺塔问题与树的遍历功能示例

    本文实例讲述了C++基于递归算法解决汉诺塔问题与树的遍历功能.分享给大家供大家参考,具体如下: 递归是把问题转化为规模缩小的同类问题,然后迭代调用函数(或过程)求得问题的解.递归函数就是直接或间接调用自身的函数. 递归两要素:递归关系和递归边界(终止条件),递归关系确定了迭代的层次结构,需要深入了解并分解问题:终止条件保证了程序的有穷性. 递归的应用有很多,常见的包括:阶乘运算.斐波那契数列.汉诺塔.数的遍历,还有大名鼎鼎的快排等等.理论上,递归问题都可以由多层循环来实现.递归的每次调用都会消耗

  • Java基于栈方式解决汉诺塔问题实例【递归与非递归算法】

    本文实例讲述了Java基于栈方式解决汉诺塔问题.分享给大家供大家参考,具体如下: /** * 栈方式非递归汉诺塔 * @author zy * */ public class StackHanoi { /** * @param args */ public static void main(String[] args) { System.out.println("我们测试结果:"); System.out.println("递归方式:"); hanoiNormal(

  • java基于递归算法实现汉诺塔问题实例

    本文实例讲述了java基于递归算法实现汉诺塔问题.分享给大家供大家参考,具体如下: package test; import java.util.List; import java.util.ArrayList; import java.util.Scanner; import sun.net.www.content.audio.x_aiff; /** * @author 年浩 * */ public class test { public static void move(char x,cha

  • C语言编程递归算法实现汉诺塔

    汉诺塔 法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针.印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔.不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面.僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔.庙宇和众生也都将同归于尽. 这个传说挺有意思的,这个传说

  • Java用递归方法解决汉诺塔问题详解

    目录 前言 一.问题描述 二.问题分析 三.解决方案 四.示例 前言 博主之前有写过关于递归问题的思维模式: 递归的思路 下面将用这种思维模式来求解经典汉诺塔问题. 一.问题描述 汉诺塔(又称河内塔)问题是源于印度一个古老传说.大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘. 大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上. 并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘. 问应该如何操作? 玩法如下: 1.有三

  • C#解决汉诺塔问题DEMO

    汉诺塔问题是学习递归的入门问题,这里用C#简单实现了一个汉诺塔之间传递盘子的小程序 通过简单绘图实现盘子在几个塔之间的转换: namespace 汉诺塔 { //盘子类 class HanioItem { public int HanoiItemHeight { get; set; }//盘子的高度 public int HanoiItemWidth { get; set; }//盘子的宽度 public Point HanoiItemPoint { get; set; }//画盘子的起始点 }

  • 利用python实现汉诺塔游戏

    本文实例为大家分享了python实现汉诺塔游戏的具体代码,供大家参考,具体内容如下 一.汉诺塔 汉诺塔问题是一个经典的递归问题,对于这个问题,我们可以把它简单的去看成是如何用n-1去表示n. 在A,B,C三个柱子上,我们先假设A柱上只有两个盘子,那么很简单,只需要把最上面的那个盘子移到B柱上,再把A柱上最下面的盘子移到C柱上,最后把B柱的盘子移到C柱就可以了. 假设我们有n个盘子,那么可以把最下面的盘子看成是第n个盘子,而我们要做的是把上面n-1个盘子移到B柱上,再把第n个盘子移到C柱.我们可以

  • Java使用递归法解决汉诺塔问题的代码示例

    汉诺(Hanoi)塔问题:古代有一个梵塔,塔内有三个座A.B.C,A座上有n个盘子,盘子大小不等,大的在下,小的在上(如图). 有一个和尚想把这n个盘子从A座移到B座,但每次只能允许移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下,小盘在上.在移动过程中可以利用B座,要求打印移动的步骤.如果只有一个盘子,则不需要利用B座,直接将盘子从A移动到C. 如果有2个盘子,可以先将盘子1上的盘子2移动到B:将盘子1移动到c:将盘子2移动到c.这说明了:可以借助B将2个盘子从A移动到C,当然,

随机推荐