zoukankan      html  css  js  c++  java
  • Hanoi递归、Hanoi非递归(仿系统递归)和Hanoi非递归规律 实现

    我的 Hanoi 算法Java实现。

    通过三个函数,分别对Hanoi进行递归、非递归和非递归规律实现。

    程序如下:

    View Code
      1 /*
      2  * Hanoi塔游戏 问题描述:
      3  * 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。
      4  * 大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照
      5  * 大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小
      6  * 顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在
      7  * 三根柱子之间一次只能移动一个圆盘。
      8  * 
      9  * fuction:实现 hanoi塔
     10  *             1.递归实现
     11  *             2.非递归实现
     12  * author:iGeneral
     13  * date:2013.04.26
     14  * 
     15  * expe:
     16  *         1.注意:塔的状态:当status=1时,表示可以直接将该Disk移动到目标塔
     17  *                 而不是用Disk的id来判断输出
     18  *         2.System.out.println();
     19           System.out.println((int)3.3%3);
     20           没有(int)时,输出:0.299999
     21           加上(int)后,输出:0
     22  */
     23 package part03.chapter10;
     24 
     25 import java.util.Scanner;
     26 
     27 public class _2exercise {
     28 
     29     public static void main(String[] args) {
     30 
     31         Scanner scanner = new Scanner(System.in);
     32         System.out.println("请输入Hanoi碟子的数量:");
     33         int diskNum = scanner.nextInt();
     34         Hanoi hanoi = new Hanoi();
     35         System.out.println("递归实现:");
     36         hanoi.play_recursive(diskNum, 'A', 'B', 'C');
     37         System.out.println("非递归实现(模仿递归思想):");
     38         hanoi.play_non_recursive(diskNum);
     39         System.out.println("非递归实现(根据Hanoi规律):");
     40         hanoi.play_regular(diskNum);
     41 
     42     }
     43 
     44 }
     45 
     46 class Hanoi {
     47 
     48     // 递归实现
     49     public void play_recursive(int num, char A, char B, char C) {
     50         if (num == 1) {
     51             System.out.println(A + " -> " + C);
     52             return;
     53         } else {
     54             play_recursive(num - 1, A, C, B);
     55             System.out.println(A + " -> " + C);
     56             play_recursive(num - 1, B, A, C);
     57         }
     58 
     59     }
     60 
     61     // 非递归实现:模仿递归思想
     62     public void play_non_recursive(int diskNum) {
     63         Stack stack = new Stack();
     64         stack.push(new Disk(diskNum, 'A', 'B', 'C'));
     65         Disk popDisk = null;
     66         while ((popDisk = stack.pop()) != null) {
     67             if (popDisk.status == 1) {
     68                 System.out.println(popDisk.A + " -> " + popDisk.C);
     69             } else {
     70                 // 反顺序添加
     71                 // 将执行移动 popDisk 的下一步的Disk添加到Stack
     72                 stack.push(new Disk(popDisk.status - 1, popDisk.B, popDisk.A,
     73                         popDisk.C));
     74                 // 将一个status为 "1" 且移动顺序与 popDisk 相同的Disk 添加到Stack中
     75                 stack.push(new Disk(1, popDisk.A, popDisk.B, popDisk.C));
     76                 // 将执行移动 popDisk 的前一步的Disk添加到Stack中
     77                 stack.push(new Disk(popDisk.status - 1, popDisk.A, popDisk.C,
     78                         popDisk.B));
     79             }
     80         }
     81     }
     82 
     83     // 非递归实现:根据Hanoi规律
     84     public void play_regular(int diskNum) {
     85 
     86         // 根据规律,需要根据 Disk 的个数,多塔的位置进行调整
     87         // 塔的个数为偶数时,将三个塔按“A->B->C”的顺序排列成三角形
     88         // 塔的个数为奇数时,将三个塔按"A->C->B"的顺序排列成三角形
     89         // 将diskNum个Disk按”上小下大“的顺序放在A塔中(堆栈实现),同时将B塔和C塔置空
     90         Stack_play_regular A = new Stack_play_regular('A');
     91         Stack_play_regular B = new Stack_play_regular('B');
     92         Stack_play_regular C = new Stack_play_regular('C');
     93         for (int i = diskNum; i > 0; i--) {
     94             A.push(i);
     95         }
     96         // 将三个塔模拟成三角形形状排列
     97         Stack_play_regular[] towers = new Stack_play_regular[3];
     98         towers[0] = A;
     99         if (diskNum % 2 == 0) {
    100             towers[1] = B;
    101             towers[2] = C;
    102         } else {
    103             towers[1] = C;
    104             towers[2] = B;
    105         }
    106         // 最小Dish所在的塔,通过该塔在towers中的
    107         int towerOfMinimunDisk = 0;
    108         // 根据证明:n个Disk移动完成至少需要2^n-1次
    109         // 不断交替进行以下两步
    110         // 将最小的Disk按以上塔的顺序下移到下一个塔
    111         // 对除了最小Disk所在的塔的另外两个塔进行操作,可能出现两种情况
    112         // 情况一:一个塔中没有Disk,此时将存在Disk的塔最上面的Disk移动到没Disk的塔上
    113         // 情况二:两个塔都有Disk,此时对他们最上面的塔进行比较,将较小的Disk移动到较大的Disk上
    114         // 不会存在两个塔都没有Disk的情况,除非移动已经完成或未开始或只有一个盘子时的移动
    115         int ii = 0;
    116         for (int i = 0; i < (Math.pow(2, diskNum) - 1);) {// --------------注意在此处不进行i++
    117             // 取出三个塔,使代码更清晰
    118             Stack_play_regular tower = towers[towerOfMinimunDisk];
    119             Stack_play_regular tower_1 = towers[(int) ((towerOfMinimunDisk + 1) % 3)];
    120             Stack_play_regular tower_2 = towers[(int) ((towerOfMinimunDisk + 2) % 3)];
    121             // 移动最小的盘子
    122             System.out.println(tower.name + " -> " + tower_1.name);
    123             tower_1.push(tower.pop());
    124             i++;// --------------注意在此处进行i++
    125             towerOfMinimunDisk = (int) ((towerOfMinimunDisk + 1) % 3);
    126             // ------------注意此时对三个tower进行重新赋值
    127             tower = towers[towerOfMinimunDisk];
    128             tower_1 = towers[(int) ((towerOfMinimunDisk + 1) % 3)];
    129             tower_2 = towers[(int) ((towerOfMinimunDisk + 2) % 3)];
    130             // 对另外两个塔进行处理
    131             if ((tower_2.getTop() != -1 && (tower_1.showTopDisk() > tower_2
    132                     .showTopDisk()))
    133             // --------------注意要再加上 tower_2.getTop() != -1
    134             // 进行判断,否则可能数组访问越界
    135                     || (tower_1.getTop() == -1 && tower_2.getTop() != -1)) {
    136                 System.out.println(tower_2.name + " -> " + tower_1.name);
    137                 tower_1.push(tower_2.pop());
    138                 i++;// --------------注意在此处进行i++
    139             } else if (((tower_1.getTop() != -1 && tower_1.showTopDisk() < tower_2
    140                     .showTopDisk()))
    141             // --------------注意要再加上 tower_1.getTop() != -1
    142             // 进行判断,否则可能数组访问越界
    143                     || (tower_1.getTop() != -1 && tower_2.getTop() == -1)) {
    144                 System.out.println(tower_1.name + " -> " + tower_2.name);
    145                 tower_2.push(tower_1.pop());
    146                 i++;// --------------注意在此处进行i++
    147             }
    148             ii = i;
    149         }
    150         System.out.println(ii);
    151     }
    152 
    153 }
    154 
    155 // 存放信息的结构体
    156 class Disk {
    157     // 从A塔通过B塔移动到C塔
    158     char A;
    159     char B;
    160     char C;
    161     // 塔的状态:当status=1时,表示可以直接将该Disk移动到目标塔
    162     int status;
    163 
    164     // 重写构造函数
    165     public Disk(int status, char A, char B, char C) {
    166         this.status = status;
    167         this.A = A;
    168         this.B = B;
    169         this.C = C;
    170     }
    171 }
    172 
    173 // 存放Disk的栈
    174 class Stack {
    175     // 用来存储盘子的数组
    176     Disk[] disks = new Disk[10000];
    177     // 塔顶
    178     private int top = 0;
    179 
    180     // 查看栈顶
    181     public Disk stackTop() {
    182         return disks[top];
    183     }
    184 
    185     // 出栈
    186     public Disk pop() {
    187         if (top != 0) {
    188             top--;
    189             return disks[top + 1];
    190         } else {
    191             return null;
    192         }
    193     }
    194 
    195     // 入栈
    196     public void push(Disk disk) {
    197         top++;
    198         disks[top] = disk;
    199     }
    200 }
    201 
    202 // 为 play_regular(int diskNum) 创建的 Stack 类
    203 // 以 diskId 来表示 Disk 对象
    204 class Stack_play_regular {
    205     // 塔名
    206     char name;
    207     // 塔顶
    208     private int top = -1;
    209 
    210     public int getTop() {
    211         return top;
    212     }
    213 
    214     // 通过数组实现Stack,最多64个Disk
    215     int[] stack = new int[64];
    216 
    217     // 重写构造函数,初始化塔的名字name
    218     public Stack_play_regular(char name) {
    219         this.name = name;
    220     }
    221 
    222     // 查看栈顶
    223     public int showTopDisk() {
    224         if (top == -1) {
    225             return -1;
    226         }
    227         return stack[top];
    228     }
    229 
    230     // 入栈
    231     public void push(int diskId) {
    232         stack[++top] = diskId;
    233     }
    234 
    235     // 出栈
    236     public int pop() {
    237         return stack[top--];
    238     }
    239 }
    欢迎转载,欢迎批评指正! 转载请注明: 转自博客园,转载地址:http://www.cnblogs.com/igeneral/
  • 相关阅读:
    Java操作Excel之POI简单例子
    机器学习之KNN算法
    机器学习之sklearn数据集
    数据分析之matplotlib
    数据分析之pandas
    数据分析之numpy
    python模块contextlib
    前端jsonp解决跨域问题
    django media和static配置
    Django之数据库迁移和创建
  • 原文地址:https://www.cnblogs.com/igeneral/p/3070025.html
Copyright © 2011-2022 走看看