diff --git a/体系学习班/class17/Code02_Hanoi.java b/体系学习班/class17/Code02_Hanoi.java index 3d9ba6e..5209651 100644 --- a/体系学习班/class17/Code02_Hanoi.java +++ b/体系学习班/class17/Code02_Hanoi.java @@ -1,5 +1,6 @@ package class17; +import java.util.HashSet; import java.util.Stack; public class Code02_Hanoi { @@ -87,41 +88,67 @@ public class Code02_Hanoi { } public static class Record { - public boolean finish1; - public int base; + public int level; public String from; public String to; public String other; - public Record(boolean f1, int b, String f, String t, String o) { - finish1 = false; - base = b; + public Record(int l, String f, String t, String o) { + level = l; from = f; to = t; other = o; } } + // 之前的迭代版本,很多同学表示看不懂 + // 所以我换了一个更容易理解的版本 + // 看注释吧!好懂! + // 你把汉诺塔问题想象成二叉树 + // 比如当前还剩i层,其实打印这个过程就是: + // 1) 去打印第一部分 -> 左子树 + // 2) 打印当前的动作 -> 当前节点 + // 3) 去打印第二部分 -> 右子树 + // 那么你只需要记录每一个任务 : 有没有加入过左子树的任务 + // 就可以完成迭代对递归的替代了 public static void hanoi3(int N) { if (N < 1) { return; } + // 每一个记录进栈 Stack stack = new Stack<>(); - stack.add(new Record(false, N, "left", "right", "mid")); + // 记录每一个记录有没有加入过左子树的任务 + HashSet finishLeft = new HashSet<>(); + // 初始的任务,认为是种子 + stack.add(new Record(N, "left", "right", "mid")); while (!stack.isEmpty()) { + // 弹出当前任务 Record cur = stack.pop(); - if (cur.base == 1) { + if (cur.level == 1) { + // 如果层数只剩1了 + // 直接打印 System.out.println("Move 1 from " + cur.from + " to " + cur.to); - if (!stack.isEmpty()) { - stack.peek().finish1 = true; - } } else { - if (!cur.finish1) { + // 如果不只1层 + if (!finishLeft.contains(cur)) { + // 如果当前任务没有加入过左子树的任务 + // 现在就要加入了! + // 把当前的任务重新压回去,因为还不到打印的时候 + // 再加入左子树任务! + finishLeft.add(cur); stack.push(cur); - stack.push(new Record(false, cur.base - 1, cur.from, cur.other, cur.to)); + stack.push(new Record(cur.level - 1, cur.from, cur.other, cur.to)); } else { - System.out.println("Move " + cur.base + " from " + cur.from + " to " + cur.to); - stack.push(new Record(false, cur.base - 1, cur.other, cur.to, cur.from)); + // 如果当前任务加入过左子树的任务 + // 说明此时已经是第二次弹出了! + // 说明左子树的所有打印任务都完成了 + // 当前可以打印了! + // 然后加入右子树的任务 + // 当前的任务可以永远的丢弃了! + // 因为完成了左子树、打印了自己、加入了右子树 + // 再也不用回到这个任务了 + System.out.println("Move " + cur.level + " from " + cur.from + " to " + cur.to); + stack.push(new Record(cur.level - 1, cur.other, cur.to, cur.from)); } } } @@ -132,8 +159,8 @@ public class Code02_Hanoi { hanoi1(n); System.out.println("============"); hanoi2(n); -// System.out.println("============"); -// hanoi3(n); + System.out.println("============"); + hanoi3(n); } }