汉诺塔算法

杀马特。学长 韩版系。学妹 提交于 2019-11-30 21:15:30

 

 

有A、B和C 3跟柱子,在A上从下往上按照从小到大的顺序放着64个圆盘,以B为中介,把盘子全部移动到C上。移动过程中,要求任意盘子的下面要么没有盘子,要么只能有比它大的盘子。

 

 * 思想:采用递归的方法来接

 *      1. 先将A上面的n-1个盘子,移到B柱上

 *      2. 然后把A上最大的一个盘子放到C上去

 *      3. 然后把B上面的n-1个盘子移到A上去

 *

 * 步骤:

 *      汉若塔用递归思考首先考虑一种临界状态,把n-1个上面的盘从A—B, 就是把n从A移动到C,最后把n-1个盘从B---C,

 *      (注意在考虑把n-1个盘从B---C的时候就出现递归调用,如果把A,B盘交换就又重复上面的流程了,最后到n = 1的时候就返回)

 *

 * 伪代码:

 *  public void run(int n, char a, char b, char c)

    {

        if(n==1)

        {

            move(n,a,c) //等于1的时候把盘从A移动到C

        }else

        {

            run(n-1,a,b,c);//递归调用把a上面的n-1个盘移动到B上,怎么表示移动?把柱子交换不就是移动了。

            move(n,a,c);

            run(n-1,b,a,c);//意图是把n-1个盘从B移动到A上。

        }

         

    }      

 *

package cglib;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Hashtable;  

 

public class StringNumber {
    public static void main(String args[]) throws Exception {
                int n;
                BufferedReader buf =
                         new BufferedReader(new InputStreamReader(System.in));
                System.out.print("请输入盘数:");
                n = Integer.parseInt(buf.readLine());
                StringNumber hanoi = new StringNumber();
                hanoi.move(n, 'A', 'B', 'C');
            }
        
            public void move(int n, char a, char b, char c) {
                if (n == 1)
                     System.out.println("盘 " + n + " 由 " + a + " 移至 " + c);
                else {
                    move(n - 1, a, c, b);
                    System.out.println("盘 " + n + " 由 " + a + " 移至 " + c);
                     move(n - 1, b, a, c);
                 }
             }
    
}
      


输出:

请输入盘数:5
盘 1 由 A 移至 C
盘 2 由 A 移至 B
盘 1 由 C 移至 B
盘 3 由 A 移至 C
盘 1 由 B 移至 A
盘 2 由 B 移至 C
盘 1 由 A 移至 C
盘 4 由 A 移至 B
盘 1 由 C 移至 B
盘 2 由 C 移至 A
盘 1 由 B 移至 A
盘 3 由 C 移至 B
盘 1 由 A 移至 C
盘 2 由 A 移至 B
盘 1 由 C 移至 B
盘 5 由 A 移至 C
盘 1 由 B 移至 A
盘 2 由 B 移至 C
盘 1 由 A 移至 C
盘 3 由 B 移至 A
盘 1 由 C 移至 B
盘 2 由 C 移至 A
盘 1 由 B 移至 A
盘 4 由 B 移至 C
盘 1 由 A 移至 C
盘 2 由 A 移至 B
盘 1 由 C 移至 B
盘 3 由 A 移至 C
盘 1 由 B 移至 A
盘 2 由 B 移至 C
盘 1 由 A 移至 C

 

 ①如果只能移动到相邻的  那么n个圆盘需要  
  f(n)=(3^n)-1 次
②如果不加上只能移动到相邻的限制的话     那么n个圆盘需要  

  f(n)=(2^n)-1次

  1. public class Hanoi {  
  2.   
  3.     /** 
  4.      * @count记录是第几次移动 
  5.      */  
  6.     private static int count = 0;  
  7.   
  8.     /** 
  9.      * @Describe_将塔座x上按直径大小自上而下编码为123...n个圆盘按规则一到塔座Z上_y做辅助塔座 
  10.      * @param n圆盘的格式 
  11.      * @param x起始圆盘的位置 
  12.      * @param y辅助塔座 
  13.      * @param z目标塔座 
  14.      */  
  15.     public static void hanoi(int n, char x, char y, char z) {  
  16.         if (n == 1) {  
  17.             move(x, 1, z);//  
  18.         } else {  
  19.             hanoi(n - 1, x, z, y);// 将前n-1个从x移动到y,z当辅助  
  20.             move(x, n, z);// 将变化为n的圆盘从x移动到z  
  21.             hanoi(n - 1, y, x, z);// 再将前n-1个圆盘从y移动到z,x当辅助  
  22.         }  
  23.     }  
  24.   
  25.     /** 
  26.      * @Describe_移动操作_将编号为n的圆盘从x移动到z 
  27.      * @param x 
  28.      * @param n 
  29.      * @param z 
  30.      */  
  31.     public static void move(char x, int n, char z) {  
  32.         System.out.println("第 " + (++count) + "次移动  :" + n + "号圆盘," + x + "-->"  
  33.                 + z);  
  34.     }  
  35.   
  36.     /** 
  37.      * @Describe_规则再次变化_再加上一个只能移动到相邻的限制条件 
  38.      * @param n 
  39.      * @param x 
  40.      * @param y 
  41.      * @param z 
  42.      */  
  43.     public static void hanoi2(int n, char x, char y, char z) {  
  44.         if (n == 1) {  
  45.             move(x, 1, y);//  
  46.             move(y, 1, z);//  
  47.         } else {  
  48.             hanoi2(n - 1, x, y, z);// 将前n-1个从x移动到z,y当辅助  
  49.             move(x, n, y);// 将变化为n的圆盘从x移动到y  
  50.             hanoi2(n - 1, z, y, x);// 再将前n-1个圆盘从z移动到x,y当辅助  
  51.             move(y, n, z);// 将变化为n的圆盘从y移动到z  
  52.             hanoi2(n - 1, x, y, z);// 将前n-1个从x移动到z,y当辅助  
  53.         }  
  54.     }  
  55.   
  56.     public static void main(String[] args) {  
  57. //      Hanoi.hanoi(4, 'x', 'y', 'z');//------可以移动到相邻的或者不相邻的  
  58. //      Hanoi.hanoi2(4, 'x', 'y', 'z');//-----只能移动到相邻的  
  59.     }  

用栈实现:

package cglib;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Stack;  

 

public class StringNumber {
     //塔  
    class Tower<E> {  
       //塔编号  
       private int number;  
       //塔名称  
       private String name;  
       //存放盘子的栈  
       private Stack<E> stack = new Stack<E>();  
         
       public Tower(int number,String name) {  
           this.number = number;  
           this.name = name;  
       }  
                
       public int getNumber() {  
           return number;  
       }  
   
       public String getName() {  
           return name;  
       }  
   
       public Stack<E> getStack() {  
           return stack;  
       }  
         
    }  
      
    //盘子  
    class Tray {  
       //盘子编号  
       private int number;  
       //盘子名称  
       private String name;  
         
       public Tray(int number,String name) {  
           this.number = number;  
           this.name = name;  
       }  
         
       public int getNumber() {  
           return number;  
       }  
         
       public String getName() {  
           return name;  
       }  
         
       public String toString() {  
           return name;  
       }  
    }  
      
    public <T> void hanoi(int num,Tower<T> from,Tower<T> middle,  
           Tower<T> to) {  
       if(num == 1) {  
           move(from,middle,to);  
       } else {  
           //将num-1个盘子从from塔上移到middle塔上  
           hanoi(num-1,from,to,middle);  
           //将第num个盘子移到to塔上  
           move(from,middle,to);  
           //将num-1个盘子从middle塔上移到to塔上  
           hanoi(num-1,middle,from,to);  
       }  
    }  
      
    private <E> void move(Tower<E> from,Tower<E> middle ,Tower<E> to) {  
       E tray = from.getStack().pop();  
       to.getStack().push(tray);  
       StringBuilder sb = new StringBuilder();  
       sb.append("=====================Hanoi.move()======================\n")  
       .append(" Move tray : ").append(((Tray)tray).getName())  
       .append(" from ").append(from.getName()).append(" to ")  
       .append(to.getName()).append("\n ")  
       .append(from.getName()).append(":").append(format(from)).append(",")  
       .append(middle.getName()).append(":").append(format(middle)).append(",")  
       .append(to.getName()).append(":").append(format(to));  
       System.out.println(sb.toString());  
    }  
    
    private <E> String format(Tower<E> tower) {  
       Iterator<E> i = tower.getStack().iterator();  
       if (! i.hasNext())  
           return "[]";  
       StringBuilder sb = new StringBuilder();  
       sb.append('[');  
       while(i.hasNext()) {  
           sb.append(i.next().toString()).append(",");  
       }  
       sb.replace(sb.length()-1, sb.length(), "]");  
       return sb.toString();  
    }  
 
    public static void main(String[] args) {  
        StringNumber hanoi = new StringNumber();  
       Tower<Tray> from = hanoi.new Tower<Tray>(1, "1号塔");  
       Tower<Tray> middle = hanoi.new Tower<Tray>(2, "2号塔");  
       Tower<Tray> to = hanoi.new Tower<Tray>(3, "3号塔");  
       int num = 4;  
       for (int i = num; i >0; i--) {  
           Tray tray = hanoi.new Tray(i,i+"号盘子");  
           from.getStack().push(tray);  
       }  
       hanoi.hanoi(num, from, middle, to);  
    }
    
}
      


输出:

=====================Hanoi.move()======================
 Move tray : 1号盘子 from 1号塔 to 2号塔
 1号塔:[4号盘子,3号盘子,2号盘子],3号塔:[],2号塔:[1号盘子]
=====================Hanoi.move()======================
 Move tray : 2号盘子 from 1号塔 to 3号塔
 1号塔:[4号盘子,3号盘子],2号塔:[1号盘子],3号塔:[2号盘子]
=====================Hanoi.move()======================
 Move tray : 1号盘子 from 2号塔 to 3号塔
 2号塔:[],1号塔:[4号盘子,3号盘子],3号塔:[2号盘子,1号盘子]
=====================Hanoi.move()======================
 Move tray : 3号盘子 from 1号塔 to 2号塔
 1号塔:[4号盘子],3号塔:[2号盘子,1号盘子],2号塔:[3号盘子]
=====================Hanoi.move()======================
 Move tray : 1号盘子 from 3号塔 to 1号塔
 3号塔:[2号盘子],2号塔:[3号盘子],1号塔:[4号盘子,1号盘子]
=====================Hanoi.move()======================
 Move tray : 2号盘子 from 3号塔 to 2号塔
 3号塔:[],1号塔:[4号盘子,1号盘子],2号塔:[3号盘子,2号盘子]
=====================Hanoi.move()======================
 Move tray : 1号盘子 from 1号塔 to 2号塔
 1号塔:[4号盘子],3号塔:[],2号塔:[3号盘子,2号盘子,1号盘子]
=====================Hanoi.move()======================
 Move tray : 4号盘子 from 1号塔 to 3号塔
 1号塔:[],2号塔:[3号盘子,2号盘子,1号盘子],3号塔:[4号盘子]
=====================Hanoi.move()======================
 Move tray : 1号盘子 from 2号塔 to 3号塔
 2号塔:[3号盘子,2号盘子],1号塔:[],3号塔:[4号盘子,1号盘子]
=====================Hanoi.move()======================
 Move tray : 2号盘子 from 2号塔 to 1号塔
 2号塔:[3号盘子],3号塔:[4号盘子,1号盘子],1号塔:[2号盘子]
=====================Hanoi.move()======================
 Move tray : 1号盘子 from 3号塔 to 1号塔
 3号塔:[4号盘子],2号塔:[3号盘子],1号塔:[2号盘子,1号盘子]
=====================Hanoi.move()======================
 Move tray : 3号盘子 from 2号塔 to 3号塔
 2号塔:[],1号塔:[2号盘子,1号盘子],3号塔:[4号盘子,3号盘子]
=====================Hanoi.move()======================
 Move tray : 1号盘子 from 1号塔 to 2号塔
 1号塔:[2号盘子],3号塔:[4号盘子,3号盘子],2号塔:[1号盘子]
=====================Hanoi.move()======================
 Move tray : 2号盘子 from 1号塔 to 3号塔
 1号塔:[],2号塔:[1号盘子],3号塔:[4号盘子,3号盘子,2号盘子]
=====================Hanoi.move()======================
 Move tray : 1号盘子 from 2号塔 to 3号塔
 2号塔:[],1号塔:[],3号塔:[4号盘子,3号盘子,2号盘子,1号盘子]

或者:

  1. import java.util.Stack;  
  2.   
  3. public class Demo {  
  4.   
  5.       public static void main(String[] args) {  
  6.              // TODO Auto-generated method stub  
  7.              int n=3;  
  8.              int disks=5;  
  9.             Tower[] towers= new Tower[ n];  
  10.              for( int i=0; i< n; i++){  
  11.                    towers[ i]= new Tower( i);  
  12.             }  
  13.               
  14.              for( int i= disks; i>=0; i--){  
  15.                    towers[0].add( i);  
  16.             }  
  17.              towers[0].moveDisks( disks, towers[2], towers[1]);  
  18.       }  
  19. }  
  20.   
  21. class Tower{  
  22.       public  Stack<Integer> disks;  
  23.       public int index;  
  24.         
  25.       public Tower(int index){  
  26.              disks= new Stack<Integer>();  
  27.              this. index= index;  
  28.       }  
  29.         
  30.       public int getIndex(){  
  31.              return this. index;  
  32.       }  
  33.         
  34.       public void add(int d){  
  35.              if(! disks.isEmpty()&& disks.peek()<= d)  
  36.                   System. out.println( "Error placing disk"+d);  
  37.              else  
  38.                    disks.push( d);  
  39.       }  
  40.         
  41.       //将orgin顶端的盘子移到destination  
  42.       public void movetoTop(Tower t){  
  43.              int top= disks.pop();  
  44.              t.add( top);  
  45.             System. out.println( "Move disk "+ top+ " from "+this.getIndex()+" to "+t.getIndex());  
  46.       }  
  47.         
  48.   
  49.       public void moveDisks( int n,Tower destination,Tower buffer){  
  50.              if( n>0){  
  51.                    //将顶端n-1个盘子从origin移到buffer  
  52.                   moveDisks( n-1, buffer, destination);  
  53.                    this.movetoTop( destination);  
  54.                    //将顶部n-1个盘子从buffer移到destination,将origin用作缓冲区  
  55.                    buffer.moveDisks( n-1, destination, this);  
  56.             }  
  57.       }  
  58. }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!