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;
            }
        }
    }
  • 相关阅读:
    Win7 usb无法识别,感叹号,没有盘符
    MVMM 中的ViewModel 实现IsLoading进度条
    菜鸟喜欢的C# 入门认识和添加,修改,删除 文件夹 文件 大全(转)
    (转)windows负载平衡
    关于刷新页面和用法.(转)
    bat文件调用dos命令 (dos淘金)
    flash新闻轮转:图片和链接从数据库读取之我见
    dling 624+and 2100ap && wireless card&wifi
    html与css小技巧
    小型系统数据库安全小结
  • 原文地址:https://www.cnblogs.com/wanjn/p/8414775.html
Copyright © 2011-2022 走看看