数据结构(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 + "\n\n";
                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();
    }

}

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

posted @ 2015-11-23 14:36  snowwolf101  阅读(1017)  评论(0编辑  收藏  举报