• 数据结构(Java)——二叉树的应用


    忙碌是一种幸福,让我们没时间体会痛苦;奔波是一种快乐,让我们真实地感受生活;疲惫是一种享受,让我们无暇空虚。

    1.表达式的二叉树求解

    1.1 构建表达式树

    表达式树扩展了LinkedBinaryTree类,提供了一个构造函数,用于把表达式树合成一棵新树,还提供了evaluate方法,用于一旦表达式树构造好之后可以对其进行递归计算。

    package ds.java.ch10;
    
    import ds.java.ch06.listImpl.ArrayUnorderedList;
    import ds.java.ch06.listImpl.UnorderedListADT;
    import ds.java.ch10.btreeImpl.BinaryTreeNode;
    import ds.java.ch10.btreeImpl.LinkedBinaryTree;
    
    /**
     * @author LbZhang
     * @version 创建时间:2015年11月23日 下午2:20:53
     * @description 表达式树
     * 
     *              表达式树是操作符和操作数集合结构
     */
    public class ExpressionTree extends LinkedBinaryTree<ExpressionTreeOp> {
    
        /**
         * 无参构造函数
         * 
         */
        public ExpressionTree() {
            super();
        }
    
        /**
         * expressionTree的构造函数
         * 
         * @param eobj
         * @param left
         * @param right
         */
        public ExpressionTree(ExpressionTreeOp eobj, ExpressionTree left,
                ExpressionTree right) {
            root = new BinaryTreeNode<ExpressionTreeOp>(eobj, left, right);
        }
    
        /**
         * 表达式树的计算
         * 
         * @return
         */
        public int evaluateTree() {
            return evaluateNode(root);
        }
    
        /**
         * 结点的递归计算
         * 
         * @param root
         * @return
         */
        private int evaluateNode(BinaryTreeNode<ExpressionTreeOp> root) {
            int result, op1, op2;
    
            ExpressionTreeOp temp;
            if (root == null) {
                result = 0;
            } else {
                temp = (ExpressionTreeOp) root.getElement();
                if (temp.isOperator()) {
                    op1 = evaluateNode(root.getLeft());
                    op2 = evaluateNode(root.getRight());
                    result = computeTerm(temp.getOperator(), op1, op2);
                }else{
                    result = temp.getValue();
                }
    
            }
    
            return result;
        }
    
        /**
         * 计算规则的定义实现
         * 
         * @param operator
         * @param op1
         * @param op2
         * @return
         */
        private int computeTerm(char operator, int op1, int op2) {
            int result = 0;
            if (operator == '+') {
                result = op1 + op2;
    
            } else if (operator == '-') {
                result = op1 - op2;
    
            } else if (operator == '*') {
                result = op1 * op2;
    
            } else if (operator == '/') {
                result = op1 / op2;
    
            }
    
            return result;
        }
    
        public String printTree() {
            UnorderedListADT<BinaryTreeNode<ExpressionTreeOp>> nodes = new ArrayUnorderedList<BinaryTreeNode<ExpressionTreeOp>>();
            UnorderedListADT<Integer> levelList = new ArrayUnorderedList<Integer>();
    
            BinaryTreeNode<ExpressionTreeOp> current;
            String result = "";
            int printDepth = this.getHeight();
            int possibleNodes = (int) Math.pow(2, printDepth + 1);
            int countNodes = 0;
    
            nodes.addToRear(root);
            Integer currentLevel = 0;
            Integer previousLevel = -1;
            levelList.addToRear(currentLevel);
    
            while (countNodes < possibleNodes) {
                countNodes = countNodes + 1;
                current = nodes.removeFirst();
                currentLevel = levelList.removeFirst();
                if (currentLevel > previousLevel) {
                    result = result + "
    
    ";
                    previousLevel = currentLevel;
                    for (int j = 0; j < ((Math.pow(2, (printDepth - currentLevel))) - 1); j++)
                        result = result + " ";
                } else {
                    for (int i = 0; i < ((Math.pow(2,
                            (printDepth - currentLevel + 1)) - 1)); i++) {
                        result = result + " ";
                    }
                }
                if (current != null) {
                    result = result + (current.getElement()).toString();
                    nodes.addToRear(current.getLeft());
                    levelList.addToRear(currentLevel + 1);
                    nodes.addToRear(current.getRight());
                    levelList.addToRear(currentLevel + 1);
                } else {
                    nodes.addToRear(null);
                    levelList.addToRear(currentLevel + 1);
                    nodes.addToRear(null);
                    levelList.addToRear(currentLevel + 1);
                    result = result + " ";
                }
    
            }
    
            return result;
        }
    
    }
    

    1.2 构建表达式结点类

    结点类中主要包含三部分,结点类型、结点的内容(char操作符或者int操作数)

    
    package ds.java.ch10;
    
    /**
     * @author LbZhang
     * @version 创建时间:2015年11月23日 下午2:21:11
     * @description
     * 
     *              表达式树中的元素 元素类
     */
    public class ExpressionTreeOp {
    
        private int termType;
        private char operator;
        private int value;
    
        public ExpressionTreeOp() {
    
        }
    
        /**
         * 3个参数的构造函数的
         * 
         * @param termType
         * @param operator
         * @param value
         */
        public ExpressionTreeOp(int termType, char operator, int value) {
            super();
            this.termType = termType;
            this.operator = operator;
            this.value = value;
        }
    
        /**
         * 判断是不是操作符号
         * @return boolean
         */
        public boolean isOperator() {
            return (termType==1);
    
        }
    
        public char getOperator() {
            return operator;
        }
    
        public int getValue() {
            return value;
        }
    
        @Override
        public String toString() {
            if(termType==1){
                return operator+"";
    
            }
            else{
                return value+"";
            }
        }
    
    
    }
    

    1.3 表达式的组装类和测试类

    package ds.java.ch10;
    
    import java.util.Scanner;
    import java.util.Stack;
    
    /**
     * @author LbZhang
     * @version 创建时间:2015年11月23日 下午4:24:04
     * @description 类说明
     */
    public class PostfixEvaluator {
    
        private String expression;
        private Stack<ExpressionTree> treeStack;// 栈
    
        /**
         * Sets up this evalutor by creating a new stack.
         */
        public PostfixEvaluator() {
            treeStack = new Stack<ExpressionTree>();
        }
    
        /**
         * Retrieves and returns the next operand off of this tree stack.
         * 
         * @param treeStack
         *            the tree stack from which the operand will be returned
         * @return the next operand off of this tree stack
         */
        private ExpressionTree getOperand(Stack<ExpressionTree> treeStack) {
            ExpressionTree temp;
            temp = treeStack.pop();
    
            return temp;
        }
    
        /**
         * Evaluates the specified postfix expression by building and evaluating an
         * expression tree.
         * 
         * @param expression
         *            string representation of a postfix expression
         * @return value of the given expression
         */
        public int evaluate(String expression) {
            ExpressionTree operand1, operand2;//两个计算需要使用的操作数
            char operator;
            String tempToken;
    
            Scanner parser = new Scanner(expression);
    
            while (parser.hasNext()) {
                tempToken = parser.next();
                operator = tempToken.charAt(0);
    
                if ((operator == '+') || (operator == '-') || (operator == '*')
                        || (operator == '/')) {
                    operand1 = getOperand(treeStack);
                    operand2 = getOperand(treeStack);
                    //如果是操作符就进行计算
                    treeStack.push(new ExpressionTree(new ExpressionTreeOp(1,
                            operator, 0), operand2, operand1));
    
                } else {
                    treeStack.push(new ExpressionTree(new ExpressionTreeOp(2, ' ',
                            Integer.parseInt(tempToken)), null, null));
                }
    
            }
    
            return (treeStack.peek()).evaluateTree();
        }
    
        /**
         * Returns the expression tree associated with this postfix evaluator.
         * 
         * @return string representing the expression tree
         */
        public String getTree() {
            return "Notree";
            //return (treeStack.peek()).printTree();
        }
    
    }
    
    
    package ds.java.ch10;
    
    import java.util.Scanner;
    
    /**
     * @author LbZhang
     * @version 创建时间:2015年11月23日 下午4:00:24
     * @description 类说明
     */
    public class PostfixTester {
    
        public static void main(String[] args) {
            String expression, again;
            int result;
    
            Scanner in = new Scanner(System.in);
    
            PostfixEvaluator evaluator = new PostfixEvaluator();
    
            expression = "5 3 - 4 * 9 +";
            result = evaluator.evaluate(expression);
            System.out.println();
            System.out.println("That expression equals " + result);
    
            System.out.println("The Expression Tree for that expression is: ");
            System.out.println(evaluator.getTree());
    
        }
    
    }
    

    2. 二叉树行为的决策树

    2.1 决策树类的构建

    决策树类主要是对二叉树的调用和扩展实现,实现决策树对象初始化和用于决策的程序实现。

    package ds.java.ch10;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.util.List;
    import java.util.Scanner;
    
    import ds.java.ch10.btreeImpl.LinkedBinaryTree;
    
    /**
     * @author LbZhang
     * @version 创建时间:2015年11月23日 下午5:15:28
     * @description 决策树类的构建
     * 
     */
    public class DecisionTree {
        private LinkedBinaryTree<String> tree;
    
        /**
         * 使用文件中的内容初始化二叉树的关联关系
         * 
         * @param filename
         * @throws FileNotFoundException
         * 
         *             这个地方需要学习的是树的链表存储的构建方式: 在链表树的存储过程中可以首先添加结点,然后根据关联关系表来添加关联
         *             或者在构建tree结点的同时设置连边关联
         * 
         */
        public DecisionTree(String filename) throws FileNotFoundException {
    
            File inputFile = new File(filename);
            Scanner scan = new Scanner(inputFile);
    
            int numberNodes = scan.nextInt();// 整型读出
    
            scan.nextLine();
            int root = 0;
            int left, right;
    
            // 用户存储二叉树的列表
            List<LinkedBinaryTree<String>> nodes = new java.util.ArrayList<LinkedBinaryTree<String>>();
    
            // 将当前的元素包装之后放到树里面
            for (int i = 0; i < numberNodes; i++)
                nodes.add(i, new LinkedBinaryTree<String>(scan.nextLine()));
    
            // 一行一行的读数据 给每一个二叉树分配自己的位置
            while (scan.hasNext()) {
                root = scan.nextInt();
                left = scan.nextInt();
                right = scan.nextInt();
                scan.nextLine();
    
                // 根据索引组合树
                nodes.set(
                        root,
                        new LinkedBinaryTree<String>((nodes.get(root))
                                .getRootElement(), nodes.get(left), nodes
                                .get(right)));
            }
            // 最后将根结点对象引用指向tree
            tree = nodes.get(root);
        }
    
        /**
         * Follows the decision tree based on user responses.
         */
        public void evaluate() {
            LinkedBinaryTree<String> current = tree;
            Scanner scan = new Scanner(System.in);
    
            while (current.size() > 1) {
                System.out.println(current.getRootElement());
                if (scan.nextLine().equalsIgnoreCase("N"))
                    current = current.getLeft();
                else
                    current = current.getRight();
            }
    
    
            System.out.println("Output the Judge Result :"+current.getRootElement());
        }
    
    }

    2.2 测试类以及测试结果

    package ds.java.ch10;
    
    import java.io.FileNotFoundException;
    
    /**
     * @author LbZhang
     * @version 创建时间:2015年11月23日 下午5:13:43
     * @description 背部疼痛诊断器
     * 
     */
    public class BackPainAnalyzer {
    
        /**
         * Asks questions of the user to diagnose a medical problem.
         */
        public static void main(String[] args) throws FileNotFoundException {
            System.out.println("So, you're having back  .");
    
            DecisionTree expert = new DecisionTree("input.txt");
            expert.evaluate();
        }
    
    }
    

    测试结果:
    模拟的专家系统

    踏实 踏踏实实~
  • 相关阅读:
    The parent project must have a packaging type of POM
    oracle中PLSQL存储过程中如何使用逗号分隔的集合(逗号分隔字符串转换为一个集合)
    此实现不是 Windows 平台 FIPS 验证的加密算法的一部分的解决办法方案
    @Modules( ... ) 多个包路径问题
    phpstorm常用操作---1、phpstorm安装插件
    phpstorm中如何配置phpunit(单元测试)
    前端性能优化---3、静态资源使用cdn加速
    前端性能优化---2、图片响应式加载
    前端性能优化---1、懒加载和复杂资源点击时再请求
    Javascript进阶课程---1、使用工厂模式创建对象
  • 原文地址:https://www.cnblogs.com/mrzhang123/p/5365826.html
Copyright © 2020-2023  润新知