java_hanoiTower汉诺塔(打印搬动过程)
package experiment1; /* hanoiTower塔 有三个杆:A、B、C,将n个圆盘(编号1、2、…、n,圆盘按从小到大编号) 从A杆移动到C杆, 要求移动中不能把大盘放在小盘上,只能小盘放在大盘上。移动的次数要求最少。 */ /* HanoiTowerTower的关键过程在于使得A柱子上的n个圆盘,通过一系列移动后(记为f(n-1)次,f(n)表示的是使得最大盘浮现出来所需要的移动步骤数),让最底层的n号圆盘浮出水面; hanoi(n - 1, origin, destination, assist);//传入描述问题的参数给hanoi方法. 现在,你要再把圆盘n移到C柱子(而且此时的C柱子还得时空的状态才能允许n盘放下(n盘是最大盘,只能放在最下面)(放完之后这时的圆盘n可以认为是固化在C住上了,没有必要再移走它了(问题规模减小了一级)), move(origin, destination); 此时B柱子上还是有n-1个圆盘(而且这n-1个盘还是有序的排在B柱子上,此时你需要将B柱子上的n-1个圆盘,在通过f(n-1)次移动,将这n-1个圆盘都移动到C柱子上(可以发现,这一目的和最初有n个圆盘时所做的事是几乎一样的, hanoi(n - 1, assist, origin, destination); 完成这一工作后,C柱上有所有的圆盘了; 将这个过程实现为递归:(此处的assist柱和destination柱在移动过程中是相对的角色;) hanoi(n - 1, origin, destination, assist); move(origin, destination); hanoi(n - 1, assist, origin, destination); */ public class HanoiTower { // /* // * n 盘子的数目 // * origin 源座 // * assist 辅助座 // * destination 目的座 // */ public int i; //n+1级规模需要分为三部分执行,需要执行两份n级规模的操作 //一个递归函数的(高效)编写需要依赖于预先对该函数有清晰的功能和参数(含义)的描述),毕竟,在编写这个函数的过程中,你得要去调用它嘛. public void hanoi(int n, char origin, char assist, char destination) {//递归入口(相对外层:location_1) if (n == 1) {//递归出口(必要部分) printMovement(origin, destination,n);//执行之后开始"归的过程",不再else } else//核心部分 { /* 递归过程中,两条语句的n-1是同一个值 */ hanoi(n - 1, origin, destination, assist);/*相对内层(越进越深,n越小,深入的过程必定先进相对外层,再进入相对内层,可以发现这个过程中assist参数和destination参数发生了对调; 这一部分的n减小至的时候,就可以调用到该深度的move方法,进而开始"归"的过程;)*/ printMovement(origin, destination,n);//归的过程中调用,这里的origin和destination 与相对外层location_1是一致的 hanoi(n - 1, assist, origin, destination); }//endElse }//endHanoi // move()方法;Print the route of the movement private void printMovement(char origin, char destination, int n) { //states[i]=origin; System.out.println("move"+ ++i +":"+" " +"disk "+ n+":" +origin + "->" + destination); } public static void main(String[] args) { HanoiTower objHanoi = new HanoiTower();//new一个HanoiTower对象,调用默认构造方法 objHanoi.hanoi(4, 'A', 'B', 'C');//调用hanoihanoi方法 } }
数组实现(不推荐,但递归原理类似)
package experiment1; /*这种方法在改变问题规模的时候的扩充性不好*/ public class HanoiTower2 { public static int count = 0; public static void main(String[] args) { char[] current = {'A', 'A', 'A', 'A'};//各个圆盘当前的所处的位置(在那个杆子上面),刚开始的时候,各个圆盘都在A上面,圆盘数目为数组维数.其中,盘从小到大排列. int n = current.length;//圆盘数目. char A = 'A', B = 'B', C = 'C';//三个杆子的名称 hanoi(current, n, A, B, C); System.out.println(String.format("总共移动次数为%d次", count)); } //核心方法:hanoi: public static void hanoi(char[] current/*杆子数组.*/, int n,/*杆的数目*/ char A, char B, char C) { //本方法中,移动圆盘这一操作通过current[i]=C或者current[n-1]=C来体系; if (n == 1) {//递归出口 int i = pickTopDisk(current, A); //返回x杆顶部圆盘编号 current[i] = C;//将i号圆盘所处的杆置为C杆(表示将i号盘移到C号杆上) count++; System.out.println("move " + count + " disk" + (i + 1) + ":" + A + "->" + C);//注意,这里的A,C都是变量 return; } hanoi(current, n - 1, A, C, B);//分支递归1 current[n - 1] = C;//current[n-1]即最大盘所处的杆号,此处要将其移动到C杆上,体现为对current[n-1]的赋值修改. count++; System.out.println("move " + count + "disk " + n + ":" + A + "→" + C); hanoi(current, n - 1, B, A, C);//分支递归2 } public static int pickTopDisk(char[] current, char x) { int i = 0; /*//返回x(当然这里一共就三个杆子,x的取值范围(A/B/C)杆 顶部圆盘(顶部体现在最先被x匹配到(小盘号一定在上面(在数组中体现在索引考前) 编号i(即第几个圆盘:i号圆盘.);而且i的取值范围为[0,1,2,...,n].;在索引越界前一定能够找到X杆的*/ while (current[i] != x) i++; return i; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了