《程序员代码面试指南》第一章 栈和队列 用栈实现汉诺塔问题

用栈实现汉诺塔,不能直接从左移到右,或者从右移到左,必须经过中间柱子。

java代码


/**
 * @Description:用栈来实现汉诺塔
 * @Author: lizhouwei
 * @CreateDate: 2018/4/5 17:30
 * @Modify by:
 * @ModifyDate:
 */
public class Chapter1_6 {
    public static final String LEFT = "left";
    public static final String MID = "mid";
    public static final String RIGHT = "right";

    public int recMoveHanoi(int n, String left, String mid, String right) {
        if (n < 1) {
            return 0;
        }
        return recMoveHanoi(n, left, mid, right, LEFT, RIGHT);
    }

    //递归实现
    public int recMoveHanoi(int n, String left, String mid, String right, String from, String to) {
        //递归的终止条件 n==1
        if (n == 1) {
            //从左或右 移动到中间的,或者从中间移动到左或者右的,都只要一步
            if (MID.equalsIgnoreCase(from) || MID.equalsIgnoreCase(to)) {
                System.out.println("move 1 from " + from + " to " + to);
                return 1;
            } else {
                System.out.println("move 1 from " + from + " to  mid");
                System.out.println("move 1 from mid to " + to);
                return 2;
            }
        }
        //从左或右 移动到中间的,或者从中间移动到左或者右的,都只要一步
        if (MID.equalsIgnoreCase(from) || MID.equalsIgnoreCase(to)) {
            //获取对应的作为辅助的柱子,例如 from为mid ,to为left,则 right为辅助的柱子,
            String another = LEFT.equalsIgnoreCase(to) || LEFT.equalsIgnoreCase(from) ? RIGHT : LEFT;
            int step1 = recMoveHanoi(n - 1, left, mid, right, from, another);
            int step2 = 1;
            System.out.println("move " + n + " from " + from + " to " + to);
            int step3 = recMoveHanoi(n - 1, left, mid, right, another, to);
            return step1 + step2 + step3;
        } else {
            //从左到右 或者 从右到左
            //1.此时 n在form上,要经过mid,才能到to ,所以先将to作为辅助,将 n-1 移到to上
            int step1 = recMoveHanoi(n - 1, left, mid, right, from, to);
            //2.此时 n在form上, n-1在to上,所以将n移到mid上
            int step2 = 1;
            System.out.println("move " + n + " from " + from + " to  mid");
            //3.此时 n-1在to上,n在mid上,from作为辅助 ,所以先将n-1移到from上
            int step3 = recMoveHanoi(n - 1, left, mid, right, to, from);
            //4.此时 n-1在from上,n在mid上,将n移到to上
            int step4 = 1;
            System.out.println("move " + n + " from  mid to " + to);
            //5.此时 n-1在from上,n在to上,所以先将n-1移到to上
            int step5 = recMoveHanoi(n - 1, left, mid, right, from, to);
            return step1 + step2 + step3 + step4 + step5;
        }
    }
//---------------------------------------------------------------------------------------------------//

    //用有序的栈来实现,充分运用了有序的特性,和同一动作不能连续重复和可逆
    public int moveHanoi(int n, String left, String mid, String right) {
        Stack<Integer> leftStack = new Stack<Integer>();
        Stack<Integer> midStack = new Stack<Integer>();
        Stack<Integer> rightStack = new Stack<Integer>();
        leftStack.push(Integer.MAX_VALUE);
        midStack.push(Integer.MAX_VALUE);
        rightStack.push(Integer.MAX_VALUE);
        //初始化左边的柱子上的元素
        for (int i = n; i > 0; i--) {
            leftStack.push(i);
        }
        int step = 0;
        //定义上一步的动作,默认为NO
        Action[] action = {Action.NO};
        while (rightStack.size() != n + 1) {
            step += moveHanoi(action, Action.ML, Action.LM, leftStack, midStack, LEFT, MID);
            step += moveHanoi(action, Action.LM, Action.ML, midStack, leftStack, MID, LEFT);
            step += moveHanoi(action, Action.RM, Action.MR, midStack, rightStack, MID, RIGHT);
            step += moveHanoi(action, Action.MR, Action.RM, rightStack, midStack, RIGHT, MID);
        }
        return step;
    }

    public int moveHanoi(Action[] action, Action preAction, Action curAction, Stack<Integer> fromStack, Stack<Integer> toStack, String from, String to) {
        if (action[0] != preAction && fromStack.peek() < toStack.peek()) {
            toStack.push(fromStack.pop());
            System.out.println("move " + toStack.peek() + " from " + from + " to " + to);
            action[0] = curAction;
            return 1;
        }
        return 0;
    }

    //测试
    public static void main(String[] args) {
        Chapter1_6 chapter = new Chapter1_6();
        //递归
        // System.out.println("step sum "+chapter.recMoveHanoi(4,LEFT,MID,RIGHT));
        System.out.println("=====================");
        //非递归
        System.out.println("step sum " + chapter.moveHanoi(4, LEFT, MID, RIGHT));
    }
}

//定义 移动的动作
enum Action {
    NO, LM, ML, MR, RM;
}
posted @ 2018-04-05 20:13  lizhouwei  阅读(207)  评论(0编辑  收藏  举报