首页 > 编程语言 >汉诺塔的图解递归算法

汉诺塔的图解递归算法

时间:2024-03-13 23:33:27浏览次数:20  
标签:char 移到 递归 圆盘 ---- 汉诺塔 图解 号盘

原文链接:https://www.cnblogs.com/dmego/p/5965835.html

如下图所示,从左到右有A、B、C三根柱子,其中A柱子上面有从小叠到大的n个圆盘,现要求将A柱子上的圆盘移到C柱子上去,期间只有一个原则:一次只能移到一个盘子且大盘子不能在小盘子上面,求移动的步骤和移动的次数

 

解:(1)n == 1

             第1次  1号盘  A---->C       sum = 1 次

       (2)  n == 2

             第1次  1号盘  A---->B

             第2次  2号盘  A---->C

             第3次  1号盘  B---->C        sum = 3 次

  (3)n == 3

        第1次  1号盘  A---->C

        第2次  2号盘  A---->B

        第3次  1号盘  C---->B

        第4次  3号盘  A---->C

        第5次  1号盘  B---->A

        第6次  2号盘  B---->C

        第7次  1号盘  A---->C        sum = 7 次

 

不难发现规律:1个圆盘的次数 2的1次方减1

       2个圆盘的次数 2的2次方减1

                         3个圆盘的次数 2的3次方减1

                         。  。   。    。   。 

                         n个圆盘的次数 2的n次方减1

 故:移动次数为:2^n - 1

算法分析(递归算法):

       我们在利用计算机求汉诺塔问题时,必不可少的一步是对整个实现求解进行算法分析。到目前为止,求解汉诺塔问题最简单的算法还是同过递归来求,至于是什么是递归,递归实现的机制是什么,我们说的简单点就是自己是一个方法或者说是函数,但是在自己这个函数里有调用自己这个函数的语句,而这个调用怎么才能调用结束呢?,这里还必须有一个结束点,或者具体的说是在调用到某一次后函数能返回一个确定的值,接着倒数第二个就能返回一个确定的值,一直到第一次调用的这个函数能返回一个确定的值。

       实现这个算法可以简单分为三个步骤:

    (1)     把n-1个盘子由A 移到 B;

    (2)     把第n个盘子由 A移到 C;

    (3)     把n-1个盘子由B 移到 C;

从这里入手,在加上上面数学问题解法的分析,我们不难发现,移到的步数必定为奇数步:

    (1)中间的一步是把最大的一个盘子由A移到C上去;

    (2)中间一步之上可以看成把A上n-1个盘子通过借助辅助塔(C塔)移到了B上,

    (3)中间一步之下可以看成把B上n-1个盘子通过借助辅助塔(A塔)移到了C上;

    public static void move(int disks,char N,char M)
    {
        System.out.println("第" + (++m) +" 次移动 : " +" 把 "+ disks+" 号圆盘从 " + N +" ->移到->  " + M);
    }
    //递归实现汉诺塔的函数
    public static void hanoi(int n,char A,char B,char C)
    {
        if(n == 1)//圆盘只有一个时,只需将其从A塔移到C塔
            TowersOfHanoi.move(1, A, C);//将编b号为1的圆盘从A移到C
        else
        {//否则
            hanoi(n - 1, A, C, B);//递归,把A塔上编号1~n-1的圆盘移到B上,以C为辅助塔
            TowersOfHanoi.move(n, A, C);//把A塔上编号为n的圆盘移到C上
            hanoi(n - 1, B, A, C);//递归,把B塔上编号1~n-1的圆盘移到C上,以A为辅助塔
        }
    }

  

图解程序运行流程:

  (1)函数hanoi(int n,char A,char B,char C)的功能是把编号为n的圆盘借助B从A移动到 C上。

  (2)函数move(int n ,char N ,char M)的功能是把1编号为n的圆盘从N 移到M上

 

标签:char,移到,递归,圆盘,----,汉诺塔,图解,号盘
From: https://www.cnblogs.com/Dongmy/p/18071843

相关文章

  • 图解Java并发编程第一章总结【精炼版】
    【第一章】图解Java并发编程Java线程的基本操作yield操作:yield操作,在基于时间片轮转的cpu调度算法中,用来放弃当前时间片sleep操作:sleep操作分为三种情况普通sleep:在指定时间内放弃cpu使用权,不释放同步锁sleep(0):作用与yield相同sleep被中断:抛出中断异常......
  • 探索 MySQL 递归查询,优雅的给树结构分页!
    一、概述递归查询是一种在数据库中处理具有层级结构数据的技术。它通过在查询语句中嵌套引用自身,以实现对嵌套数据的查询。递归查询在处理树状结构、父子关系或层级关系的数据时非常有用。在MySQL中,递归查询可以使用WITHRECURSIVE语句来实现。该语句允许我们定义一个递归查......
  • [计算理论] 1. 图灵机、递归函数与丘奇-图灵论题 Turing Machine, Recursive Function
    图灵机在研究一种自动机时,我们有两种视角语法学(Syntax),描述一个自动机是什么,如分析自动机的组成、结构。语义学(Semantics),描述一个自动机做什么,如分析自动机的语言。换句话说,前者是自动机的视角,后者是形式语言的视角。图灵机的语法图灵机的原始描述如下:一台含......
  • 关于Sql server数据类型HierarchyID 数据类型用法和递归显示完整路径
    SQLServer2008版本之后的新类型HierarchyID不知道大家有没有了解,该类型作为取代id,parentid的一种解决方案,让人非常惊喜。官方给的案例浅显易懂,但是没有实现我想要的基本功能,树形结构中完整名称路径的展示。本文末尾是一个完整路径的样例,需要更多基本操作可以参考文末微软链......
  • MYSQL: 表表达式(CTE)实现递归实例
    环境:MYSQL8.0 + windows10 1、在TEST数据库中创建 表CTE_TEST.CREATETABLE`test`.`cte_test`(test_idINT,test_nameVARCHAR(50),parent_test_idINT,created_byINT,creation_dateTIMESTAMP);例子数据:INSERTINTO`test`.`cte_test`(test_i......
  • python 递归比较两个文件夹
    以下importfilecmp,osdefcompare_folders(folder1,folder2):dcmp=filecmp.dircmp(folder1,folder2)fornameindcmp.left_only:print(f"{folder1}单独存在的文件:{name}")fornameindcmp.right_only:print(f"{folder......
  • VUE后台获取数据,并将数据递归为树接口所需数据形式
    后台获取数据形式(parentID=0的是父级,parentID不为0的,如果parentID与某个对象中的id相等,则表示为该对象的子级。) 代码转换:<script>varroomMenuDataL;//后台获取的教室数据methods:{//获取教室树getroommenu(){consttoken=this.$cookieTools.getTo......
  • 第五节:二叉树相关(反转二叉树[递归/栈]、最大路径和)
    一.反转二叉树一.题目描述  给你一棵二叉树的根节点root,反转这棵二叉树,并返回其根节点。  示例:  leetcode:https://leetcode.cn/problems/invert-binary-tree/description/  难度:【简单】二.思路分析1-递归 1.首先要有递归结束的条件 2.先写......
  • pg distinct 改写递归优化(德哥的思路)
    德哥的优化思路巨牛逼,这种递归思维真的太吊了,我目前就缺递归思路。 下面SQL1000W行数据,列的选择性很低,只有两个值('1'和'11')都是字符串类型,'1'只有一条数据,'11'有9999999行数据。慢SQL:selectdistinctcolfromtt;......
  • 递归函数-树形列表
    基本思想根据根节点没有父节点原理找到父节点;根据子节点的父id找到根节点所有的子节点;递归遍历父节点的所有子节点; privatevoidrecursionFn(List<SysDept>list,SysDeptt){//得到子节点列表List<SysDept>childList=getChildList(list,t......