zoukankan      html  css  js  c++  java
  • 二叉树的构造

    利用先序序列递归构造根节点,利用中序序列来逻辑上判断是构造左子树还是右子树

    package com.cn.sotred;
    
    /**
     * 采用先序和中序序列构造二叉树
     * 
     * @author wanjn
     *
     */
    public class MyTree {
        private Node root;// 根节点
    
        public Node getRoot() {
            return root;
        }
    
        public void setRoot(Node root) {
            this.root = root;
        }
    
        /**
         * 先序序列和中序序列构造二叉树,递归的根据先序序列和中序序列构造根节点, 然后根据逻辑人为的判断是构造左子数还是右子数
         * 
         * @param pre
         *            先序序列
         * @param i
         *            先序序列起点
         * @param j
         *            先序序列终点
         * @param mid
         *            中序序列
         * @param s
         *            中序序列起点
         * @param t
         *            中序序列终点
         */
        public MyTree(int[] pre, int i, int j, int[] mid, int s, int t) {
            root = createTree(pre, i, j, mid, s, t);
        }
    
        /**
         * 先根遍历
         */
        public void preOrder() {
            doPreOrder(root);
        }
    
    
        /**
         * 中根遍历
         */
        public void midOrder() {
            doMidOrder(root);
        }
    
        /**
         * 后根遍历
         */
        public void lastOrder() {
            doLastOrder(root);
        }
    
    
        /**
         * 得到某个节点的所有子孙节点(注意不是真子孙)
         * 
         * @param i
         *            指定节点的节点值
         */
        public void descents(int i) {
            DoDescents(root, i, 0);
        }
    
        /**
         * 递归方法最后一层需要退出,既可以是正常执行完毕的退出也可以是return的退出
         * 
         * @param node
         */
        private void doPreOrder(Node node) {
            // 先访问根节点
            System.out.print(node.value + " ");
            // 再访问左子树
            if (node.left != null) {
                doPreOrder(node.left);
            }
            // 再访问右子树
            if (node.right != null) {
                doPreOrder(node.right);
            }
    
        }
        /**
         * 得到某个节点的所有子孙节点(注意不是真子孙) 逻辑为:从根节点开始找,没找到指定节点前,标志位为0,不输出;
         * 找到指定节点后标示位置为1,之后递归该节点左右子树,因为标志位被传递下去,依然为1.标志位为1均输出节点值;
         * 然后在遍历完左右子树后,手动将标志位置为0,接下去继续遍历,因为标志位0,即使遍历了也不会输出节点值
         * 
         * @param node
         *            根节点
         * @param i
         *            指定的节点
         * @param flag
         *            标志位
         */
        private void DoDescents(Node node, int i, int flag) {
    
            if (node == null) {
                return;
            }
            // 开始
            if ((Integer) node.value == i) {
                flag = 1;
            }
            if (flag == 1) {
                System.out.print(node.value + "  ");
            }
            DoDescents(node.left, i, flag);
            DoDescents(node.right, i, flag);
            // 结束
            if ((Integer) node.value == i) {
                flag = 0;
            }
        }
    
        private void doLastOrder(Node node) {
            // 先遍历左子树
            if (node.left != null) {
                doLastOrder(node.left);
            }
    
            // 再遍历右子树
            if (node.right != null) {
                doLastOrder(node.right);
            }
            // 最后遍历根节点
            System.out.print(node.value + " ");
        }
        private Node createTree(int[] pre, int i, int j, int[] mid, int s, int t) {
            if (i > j) {
                return null;
            }
            // k用来在中序序列(从头开始找)中找根的位置
            int k = s;
            // 创建根节点,即先序序列的第一个元素
            Node node = new Node(pre[i]);
            // 在中序序列中查找该根节点的位置,从而确定,新的先序和中序序列
            while (k <= t && mid[k] != pre[i]) {
                k++;
            }
            // 在中序序列中没有找到根节点,说明序列本身有问题
            if (k > t) {
                throw new RuntimeException("不存在序列组合指定的树!");
            }
            // 创建左子树
            // 其中 k-s 表示在中序序列中左子树中节点的个数假设是q,从而可以知道先序序列从根节点开始后面的q个节点都属于左子树;
            // 依次我们可以得到左先,左中 ; 右先,右中的数组对应下标组合
            node.left = createTree(pre, i + 1, i + k - s, mid, s, k - 1);
            node.right = createTree(pre, i + k - s + 1, j, mid, k + 1, t);
    
            return node;
        }
    
        private void doMidOrder(Node node) {
            // 先遍历左子树
            if (node.left != null) {
                doMidOrder(node.left);
            }
            // 再遍历根节点
            System.out.print(node.value + " ");
            // 最后遍历右子树
            if (node.right != null) {
                doMidOrder(node.right);
            }
        }
    
        private class Node {
            Node left;// 左儿子
            Object value;// 节点值
            Node right;// 右儿子
    
            private Node(Object value) {
                this.value = value;
            }
        }
    }
  • 相关阅读:
    HDU 1114 Piggy-Bank
    HDU 2955 Robberies
    NTOJ 290 动物统计(加强版)
    POJ 3624 Charm Bracelet
    HDU 2602 Bone Collector
    POJ 1523 SPF(无向图割顶)
    HDU 5311 Hidden String
    HDU 1421 搬寝室
    HDU 1058 Humble Numbers
    POJ 3259 Wormholes(spfa判负环)
  • 原文地址:https://www.cnblogs.com/wanjn/p/8414775.html
Copyright © 2011-2022 走看看