美文网首页
汉诺塔问题

汉诺塔问题

作者: Stroman | 来源:发表于2018-02-08 19:26 被阅读16次
public class HanoiTower {
    /**
     * 汉诺塔问题。很传统的算法问题,
     * 把大问题转化为小问题的典型案例
     * 。同时它也是递归思想的极具代表
     * 性的体现。
     * 假设目前A柱上面有n个盘子,现在我们要做的是把n-1个盘子借助B盘子移动到C柱子上面。
     * 于是柱子就有了3个角色,
     * 1、源柱子。
     * 2、辅助柱子。
     * 3、目标柱子。
     * 当n=k时,从A先把k-1个盘子放在B上面,然后再把第k个盘子放到C上面去。
     * 而要把A中的k-1个盘子放在B上去,就必须借助C,此时C却充当了辅助的角色。
     * 这之后才会把第k个盘子放到C上面去。
     * 当n=k-1时,从B先把k-2个盘子放在A上面,然后再把第k-1个盘子放到C上面去。
     * 当n=k-2时,从A先把k-3个盘子放在B上面,然后再把第k-2个盘子放到C上面去。
     * @param level
     * @param sourcePillar
     * @param temporaryPillar
     * @param targetPillar
     */
    static public void hanoi0(int level,String sourcePillar,String temporaryPillar,String targetPillar) {
        if (level <= 0) {
            System.out.println("错误!");
            return;
        }
        //当只有1个待移动盘子的时候就不需要辅助柱子了
        //直接从源柱子移动到目标柱子上面就可以了
        if (level == 1) {
            System.out.println(sourcePillar + "-->" + targetPillar);
        } else {
            //把上面的level-1个盘子挪走
            hanoi0(level - 1,sourcePillar,targetPillar,temporaryPillar);
            //移动第level个盘子到目标位置上。
            hanoi0(1,sourcePillar,temporaryPillar,targetPillar);
            //下一次递归
            hanoi0(level - 1,temporaryPillar,sourcePillar,targetPillar);
        }
    }

    /**
     * 这是汉诺塔问题的非递归算法
     * 思路为首先建立完全二叉树,
     * 然后前序遍历即可。
     * 仔细观察每一步移动的步骤会
     * 发现,它的子步骤中的前一步
     * 是由该步骤的左侧柱子组成的
     * ,右步骤是由该步骤所缺失的
     * 那个柱子组成的。后一步的右
     * 侧边界是由该步骤的右侧边界
     * 柱子组成的,左侧边界是由该
     * 步骤缺失的那根柱子组成的。
     * 又因为从递归方法的实现来看
     * ,每一次回调必然产生2个结
     * 果,所以可以由父步骤生成2
     * 个子步骤。
     * 生成完全二叉树以后再观察结
     * 果发现这是二叉树的中序遍历
     * 的结果,于是就可以得出汉诺
     * 塔问题的非递归实现之一了。
     * @param level
     * @param sourcePillar
     * @param temporaryPillar
     * @param targetPillar
     */
    static public void hanoi1(int level,String sourcePillar,String temporaryPillar,String targetPillar) {
        if (level <= 0) {
            System.out.println("错误!");
            return;
        }
        //这样做可以把对符号的操作转换为对数字的操作——方便。
        String[] pillarArray = new String[3];
        pillarArray[0] = sourcePillar;
        pillarArray[1] = temporaryPillar;
        pillarArray[2] = targetPillar;
        //队列最长也就是最下面那一排叶子结点的个数了
        int queueDimension = (int) Math.pow(2,level - 1);
        HanoiObject[] objectQueue = new HanoiObject[queueDimension];
        int front = 0;
        int rear = front;
        //这里面的是自定义的一个每一步骤的状态对象。
        HanoiObject rootObject = new HanoiObject(0,2);
        objectQueue[rear] = rootObject;
        //构建完全二叉树
        while (front != (rear + 1) % queueDimension) {
            HanoiObject frontObject = objectQueue[front++ % queueDimension];
            int temporaryIndex = 3 - frontObject.getTargetPillar() - frontObject.getSourcePillar();
            HanoiObject leftChild = new HanoiObject(frontObject.getSourcePillar(),temporaryIndex);
            HanoiObject rightChild = new HanoiObject(temporaryIndex,frontObject.getTargetPillar());
            frontObject.leftChild = leftChild;
            frontObject.rightChild = rightChild;
            objectQueue[++rear % queueDimension] = leftChild;
            objectQueue[++rear % queueDimension] = rightChild;
        }
        //中序遍历
        HanoiObject[] objectStack = new HanoiObject[level];
        int objectStackPointer = -1;
        HanoiObject objectPointer = rootObject;
        while (objectStackPointer > -1 || objectPointer != null) {
            while (objectPointer != null) {
                objectStack[++objectStackPointer] = objectPointer;
                objectPointer = objectPointer.leftChild;
            }
            if (objectStackPointer > -1) {
                objectPointer = objectStack[objectStackPointer--];
                System.out.println(pillarArray[objectPointer.getSourcePillar()] + "-->" + pillarArray[objectPointer.getTargetPillar()]);
                objectPointer = objectPointer.rightChild;
            }
        }
    }

    /**
     * 这是用递归方法转换成非递归方法的通用方法转换的
     * 毫无以为这需要用到栈。
     * 根据汉诺塔的递归可以看到这是一颗三叉树。
     * @param level
     * @param sourcePillar
     * @param temporaryPillar
     * @param targetPillar
     */
    static public void hanoi2(int level,String sourcePillar,String temporaryPillar,String targetPillar) {
        if (level <= 0) {
            System.out.println("错误!");
            return;
        }
        String[] pillarArray = new String[3];
        pillarArray[0] = sourcePillar;
        pillarArray[1] = temporaryPillar;
        pillarArray[2] = targetPillar;
        //由于是三叉树所以栈中结点数最多是3 * (level - 1) + 1
        HanoiStep[] hanoiStack = new HanoiStep[3 * (level - 1) + 1];
        int hanoiStepPointer = -1;
        hanoiStack[++hanoiStepPointer] = new HanoiStep(level,0,1,2);
        while (hanoiStepPointer > -1) {
            HanoiStep popHanoiStep = hanoiStack[hanoiStepPointer--];
            if (popHanoiStep.getLevel() == 1)
                System.out.println(pillarArray[popHanoiStep.getSourcePillar()] + "-->" + pillarArray[popHanoiStep.getTargetPillar()]);
            else {
                //这是3个步骤
                hanoiStack[++hanoiStepPointer] = new HanoiStep(popHanoiStep.getLevel() - 1,popHanoiStep.getTemporaryPillar(),popHanoiStep.getSourcePillar(),popHanoiStep.getTargetPillar());
                hanoiStack[++hanoiStepPointer] = new HanoiStep(1,popHanoiStep.getSourcePillar(),popHanoiStep.getTemporaryPillar(),popHanoiStep.getTargetPillar());
                hanoiStack[++hanoiStepPointer] = new HanoiStep(popHanoiStep.getLevel() - 1,popHanoiStep.getSourcePillar(),popHanoiStep.getTargetPillar(),popHanoiStep.getTemporaryPillar());
            }
        }
    }
}
public class HanoiObject {
    private int sourcePillar;
    private int targetPillar;
    public HanoiObject leftChild = null;
    public HanoiObject rightChild = null;

    public HanoiObject(int sourcePillar, int targetPillar) {
        this.sourcePillar = sourcePillar;
        this.targetPillar = targetPillar;
    }

    public int getSourcePillar() {
        return sourcePillar;
    }

    public int getTargetPillar() {
        return targetPillar;
    }
}
public class HanoiStep {
    private int level;
    private int sourcePillar;
    private int temporaryPillar;
    private int targetPillar;

    public HanoiStep(int level, int sourcePillar, int temporaryPillar, int targetPillar) {
        this.level = level;
        this.sourcePillar = sourcePillar;
        this.temporaryPillar = temporaryPillar;
        this.targetPillar = targetPillar;
    }

    public int getLevel() {
        return level;
    }

    public int getSourcePillar() {
        return sourcePillar;
    }

    public int getTemporaryPillar() {
        return temporaryPillar;
    }

    public int getTargetPillar() {
        return targetPillar;
    }
}

相关文章

  • 汉诺塔问题与递归

    文章也同时在个人博客 http://kimihe.com/更新 汉诺塔问题(Hanoi Tower) 汉诺塔问题的...

  • 汉诺塔算法和背后的数据结构

    汉诺塔是有算法的。 很多问题都有解决办法,汉诺塔也不例外。如果汉诺塔的算法符合 Introduction to a...

  • Python使用递归解决汉诺塔问题

    汉诺塔 (http://baike.baidu.com/view/191666.htm) , 汉诺塔问题也是程序设...

  • 动态规划刷题整理(持续更新)

    (持续更新) 奇怪的汉诺塔(4柱汉诺塔) 描述汉诺塔问题,条件如下:1、这里有A、B、C和D四座塔。2、这里有n个...

  • Python汉诺塔递归算法

    汉诺塔含义: 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石...

  • 图解汉诺塔问题( Java 递归实现)

    汉诺塔简介 最近在看数据结构和算法,遇到了一个非常有意思的问题——汉诺塔问题。 先看下百度百科是怎么定义汉诺塔的规...

  • 汉诺塔问题

  • 汉诺塔问题

    问题 有三个塔a、b、ca塔上有盘子若干,大小不等,小盘在上,大盘在下,每次只移动一个盘子,现需要将a塔上的全部盘...

  • 汉诺塔问题

  • 汉诺塔问题

    题目(算法课第八课) 古代有一个梵塔,塔内有三个座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上...

网友评论

      本文标题:汉诺塔问题

      本文链接:https://www.haomeiwen.com/subject/dsxxtftx.html