算法:当只有一个盘子的时候,只需要从将A塔上的一个盘子移到C塔上。
当A塔上有两个盘子是,先将A塔上的1号盘子(编号从上到下)移动到B塔上,再将A塔上的2号盘子移动的C塔上,最后将B塔上的小盘子移动到C塔上。
当A塔上有3个盘子时,先将A塔上编号1至2的盘子(共2个)移动到B塔上(需借助C塔),然后将A塔上的3号最大的盘子移动到C塔,最后将B塔上的两个盘子借助A塔移动到C塔上。
当A塔上有n个盘子是,先将A塔上编号1至n-1的盘子(共n-1个)移动到B塔上(借助C塔),然后将A塔上最大的n号盘子移动到C塔上,最后将B塔上的n-1个盘子借助A塔移动到C塔上。
综上所述,除了只有一个盘子时不需要借助其他塔外,其余情况均一样(只是事件的复杂程度不一样)。
Python
def hanoi(n,x,y,z): if n==1: print(x,'-->',z) else: hanoi(n-1,x,z,y)#将前n-1个盘子从x移动到y上 hanoi(1,x,y,z)#将最底下的最后一个盘子从x移动到z上 hanoi(n-1,y,x,z)#将y上的n-1个盘子移动到z上 n=int(input('请输入汉诺塔的层数:')) hanoi(n,'x','y','z')
php
<?php functionhanoi($n,$x,$y,$z){ if($n==1){ move($x,1,$z); }else{ hanoi($n-1,$x,$z,$y); move($x,$n,$z); hanoi($n-1,$y,$x,$z); } } functionmove($x,$n,$z){ echo'movedisk'.$n.'from'.$x.'to'.$z.'<br>'; } hanoi(10,'x','y','z'); ?>
Java
public class Hanoi { /** * * @param n 盘子的数目 * @param origin 源座 * @param assist 辅助座 * @param destination 目的座 */ public void hanoi(int n, char origin, char assist, char destination) { if (n == 1) { move(origin, destination); } else { hanoi(n - 1, origin, destination, assist); move(origin, destination); hanoi(n - 1, assist, origin, destination); } } // Print the route of the movement private void move(char origin, char destination) { System.out.println("Direction:" + origin + "--->" + destination); } public static void main(String[] args) { Hanoi hanoi = new Hanoi(); hanoi.hanoi(3, 'A', 'B', 'C'); } }
C++
#include<iostream> using namespace std; void hanoi(int n,char a,char b,char c) { if(n==1) cout<<n<<" "<<a<<" "<<c<<endl; else { hanoi(n-1,a,c,b); cout<<n<<" "<<a<<" "<<c<<endl; hanoi(n-1,b,a,c); } } int main() { int n; cout<<"输入正整数:"<<endl; cin>>n; cout<<"结果为"<<endl; hanoi(n,'A','B','C'); return 0; }
C语言
#include<stdio.h> voidhanoi(intn,charA,charB,charC) { if(n==1) { printf("Movedisk%dfrom%cto%c ",n,A,C); } else { hanoi(n-1,A,C,B); printf("Movedisk%dfrom%cto%c ",n,A,C); hanoi(n-1,B,A,C); } } main() { intn; printf("请输入数字n以解决n阶汉诺塔问题: "); scanf("%d",&n); hanoi(n,'A','B','C'); return 0; }
汉诺塔问题的非递归实现
#include<stdio.h> #include<math.h> #include<stdlib.h> //第0位置是柱子上的塔盘数目 intzhua[100]={0},zhub[100]={0},zhuc[100]={0}; charcharis(charx,intn) //左右字符出现顺序固定,且根据n值奇偶尔不同 { switch(x) { case'A': return(n%2==0)?'C':'B'; case'B': return(n%2==0)?'A':'C'; case'C': return(n%2==0)?'B':'A'; default: return'0'; } } voidprint(charlch,charrch) //打印字符 { if(lch=='A') { switch(rch) { case'B': zhub[0]++; zhub[zhub[0]]=zhua[zhua[0]]; zhua[zhua[0]]=0; zhua[0]--; break; case'C': zhuc[0]++; zhuc[zhuc[0]]=zhua[zhua[0]]; zhua[zhua[0]]=0; zhua[0]--; break; default: break; } } if(lch=='B') { switch(rch) { case'A': zhua[0]++; zhua[zhua[0]]=zhub[zhub[0]]; zhub[zhub[0]]=0; zhub[0]--; break; case'C': zhuc[0]++; zhuc[zhuc[0]]=zhub[zhub[0]]; zhub[zhub[0]]=0; zhub[0]--; break; default: break; } } if(lch=='C') { switch(rch) { case'A': zhua[0]++; zhua[zhua[0]]=zhuc[zhuc[0]]; zhuc[zhuc[0]]=0; zhuc[0]--; break; case'B': zhub[0]++; zhub[zhub[0]]=zhuc[zhuc[0]]; zhuc[zhuc[0]]=0; zhuc[0]--; break; default: break; } } printf(" "); inti; printf("("); for(i=1;i<=zhua[0];i++) printf("%d",zhua[i]); printf(")"); printf("("); for(i=1;i<=zhub[0];i++) printf("%d",zhub[i]); printf(")"); printf("("); for(i=1;i<=zhuc[0];i++) printf("%d",zhuc[i]); printf(")"); printf(" "); } voidHannuo(intn) { //分配2^n个空间 bool*isrev; isrev=(bool*)malloc(sizeof(bool)*(int)pow(2,n)); for(inti=1;i<pow(2,n);i++) isrev[i]=false; //循环计算是否逆序 for(intci=2;ci<=n;ci++) { for(intzixh=(int)pow(2,ci-1);zixh<pow(2,ci);zixh+=4) //初始值重复一次,自增值可加4,减少循环次数。 isrev[zixh]=isrev[(int)pow(2,ci)-zixh]; //该位置为中间位置,且奇次幂逆序,偶数幂不逆序 isrev[(int)pow(2,ci)]=((ci-1)%2==0)?false:true; } charlch='A',rch; rch=(n%2==0?'B':'C'); printf("%d ",1); printf("%c->%c",lch,rch); print(lch,rch); for(intk=2;k<pow(2,n);k++) { if(k%2==0) rch=charis(lch,n); else lch=charis(rch,n); printf("%d ",k); if(isrev[k]) { printf("%c->%c",rch,lch); print(rch,lch); } else { printf("%c->%c",lch,rch); print(lch,rch); } } } intmain() { intn; printf("Inputthenum:"); scanf("%d",&n); zhua[0]=n; for(inti=1;i<=n;i++) zhua[i]=n-i+1; Hannuo(n); return0; }