关键词:
原文链接:(转载请注明出处)https://dmego.me/2016/10/16/hanoi
一.起源:
汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
二.抽象为数学问题:
如下图所示,从左到右有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上;
五,java源代码:
package demo; /** * 目的:实现汉诺塔问题求解 * 作者:Dmego 时间:2016-10-15 */ import java.util.Scanner; public class TowersOfHanoi static int m =0;//标记移动次数 //实现移动的函数 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为辅助塔 public static void main(String[] args) Scanner imput = new Scanner(System.in); char A = ‘A‘; char B = ‘B‘; char C = ‘C‘; System.out.println("******************************************************************************************"); System.out.println("这是汉诺塔问题(把A塔上编号从小号到大号的圆盘从A塔通过B辅助塔移动到C塔上去"); System.out.println("******************************************************************************************"); System.out.print("请输入圆盘的个数:"); int disks = imput.nextInt(); TowersOfHanoi.hanoi(disks, A, B, C); System.out.println(">>移动了" + m + "次,把A上的圆盘都移动到了C上"); imput.close();
六.图解程序运行流程:
(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上
七.程序运行截图:
五大常用算法一文搞懂分治算法(代码片段)
前言分治算法(divideandconquer)是五大常用算法(分治算法、动态规划算法、贪心算法、回溯法、分治界限法)之一,很多人在平时学习中可能只是知道分治算法,但是可能并没有系统的学习分治算法,本篇就带你较为全面的去认识... 查看详情
五大常用算法--分治(代码片段)
概念DivideandConquerisanalgorithmicparadigm.AtypicalDivideandConqueralgorithmsolvesaproblemusingfollowingthreesteps.Divide:Breakthegivenproblemintosubproblemsofsametype.Conquer:RecursivelysolvethesesubproblemsCombine:Appropriatelycombinetheanswer.常见应用快排/*low-->Startingindex,high--&g... 查看详情
五大常用算法:分治动态规划贪心回溯和分支界定
五大常用算法:分治、动态规划、贪心、回溯和分支界定 这五种算法引出了很多问题。慢慢的更新链接! 动态规划的五个典型算法:动态规划 1.最大连续子序列之和2.数塔问题(二叉树从上往下遍历最大和... 查看详情
[转]五大常用算法:分治动态规划贪心回溯和分支界定
...ferredfrom http://blog.csdn.net/yapian8/article/details/28240973分治算法一、基本概念 在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子... 查看详情
五大算法:分治,贪心,动态规划,回溯,分支界定(代码片段)
分治算法一、基本概念 在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可... 查看详情
五大常用算法
http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741370.html分治算法一、基本概念 在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再... 查看详情
五大常用算法
五大常用算法之一:分治算法https://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741370.html五种常用算法之二:动态规划算法https://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741374.html五大常用算法之三贪心算法https://www.cnblogs.com/steven_oyj/archive/2010/... 查看详情
五大常用算法
1.分治法 http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741370.html2.动态规划 http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741374.html3.贪心算法 http://www.cnblogs.com/steven_oyj/a 查看详情
五大常用经典算法
一、基本概念在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解... 查看详情
六中常用算法设计:穷举法分治法动态规划贪心法回溯法和分支限界法(代码片段)
算法设计之六种常用算法设计方法1.直接遍历态(穷举法) 程序运行状态是可以遍历的,遍历算法执行每一个状态,最终会找到一个最优的可行解;适用于解决极小规模或者复杂度线性增长,而线... 查看详情
五大经典算法-动态规划及其算法应用(代码片段)
前言整篇文章分析整个动态规划算法,什么是动态规划,及动态规划算法在字符串匹配中使用、分治法的差别点、动态规划优点;概念什么叫做动态规划(dynamicprogramming),它是运筹学的一个分支,是求解决策过... 查看详情
五大常用算法--dp(代码片段)
概念【geekforgeeks】DynamicProgrammingismainlyanoptimizationoverplainrecursion.Whereverweseearecursivesolutionthathasrepeatedcallsforsameinputs,wecanoptimizeitusingDynamicProgramming.Theideaistosimplystoretheresultsofsubproblems,sothatwedonothavetore-computethemwhenneededlater.Thissimpleoptimiza... 查看详情
五大常见算法策略——递归与分治策略(代码片段)
摘要:递归与分治策略是五大常见算法策略之一,分治策略的思想就是分而治之,即先将一个规模较大的大问题分解成若干个规模较小的小问题,再对这些小问题进行解决,得到的解,在将其组合起来得到最终的解。而分治与递... 查看详情
python_分治算法贪心算法动态规划算法(代码片段)
文章目录一、分治算法思想1、基本算法思想2、寻找假币示例二、贪心算法1、思想2、最大不相容活动安排示例三、动态规划1、思想2、最大和路径3、背包问题4、动态规划和贪心算法的区别一、分治算法思想分治算法是一种化繁... 查看详情
五大常用算法的简单介绍
1、递归与分治递归算法:直接或者间接不断反复调用自身来达到解决问题的方法。这就要求原始问题可以分解成相同问题的子问题。示例:阶乘、斐波纳契数列、汉诺塔问题 斐波纳契数列:又称黄金分割数列,指的是这样... 查看详情
chatgpt教你算法——分治法(代码片段)
...题和循环赛日程安排问题。1.什么是分治法分治法是一种算法设计技巧 查看详情
分治算法之快排和归并(代码片段)
分治算法思想将大问题分为小问题,从而解决小问题,最后将结果合并。分治算法一般有三个过程:分,治,合。分对应分拆大问题,治解决小问题,合将小问题答案合并起来得出最后答案。典型的分治策略有二分,快排和归并... 查看详情
八大内部排序算法之希尔堆排序插入排序算法(代码片段)
前言我们所知的八大内部的排序算法有冒泡排序、选择排序、快速排序、归并排序、链式基数排序、插入排序、希尔排序、堆排序、而这篇文章主要研究这其中的希尔排序和堆排序算法,之前的排序算法都在下面连接中介绍... 查看详情