您的位置:首页 > 编程语言 > Java开发

二叉树的应用——表达式树的原理分析与实现(Java语言)

2017-12-03 17:16 519 查看

表达式树

表达式树(expression tree)的树叶是操作数(operand),如常量或变量名,而其他节点为操作符(operator)。如下图



图1 (a+b*c)+((d*e+f)*g)的表达式树

我们可以通过递归地产生一个带括号的左表达式,然后打印出在跟出的运算符,最后再递归地产生一个带括号的右表达式从而得到一个中缀表达式。这种一般的方法(左,节点,右)的方式成为中序遍历

构造表达式树

我们现在给出一个算法来把后缀表达式转变成表达式树。

设输入为:

a b + c d e + * *

前两个符号是操作数,因此创建两颗单节点书并将它们压入栈中。



接着,+被读取,因此两棵树被弹出,一颗新的树形成,并被压入栈中。



然后,c、d、e被读入,分别创建对应的单节点树,然后压入栈中。



接下来读到+号,因此两棵树合并。



继续进行,读到*号,弹出两棵树合成一颗新的树并压入栈中。



最后,读入最后一个符号,两棵树合并,而最后的树被留在栈中。



从后缀表达式构造表达式树的实现

创建节点类BinaryNode.class

public class BinaryNode {
String element;
BinaryNode left;
BinaryNode right;

public BinaryNode(String element) {
this.element = element;
}

public BinaryNode(String element, BinaryNode left, BinaryNode right) {
this.element = element;
this.left = left;
this.right = right;
}
//为节省篇幅,getter()、setter()方法略去,请自行补充
}


常见一个ExpressionTree.class类,该类有三个静态方法,分别是:postfixToExpressionTree(String[] expressions)、printBinaryTree(int depth,BinaryNode binaryNode)和main(String[] args)。

postfixToExpressionTree(String[] expressions)方法负责将后缀表达式构造成表达式树并返回:

/**
* 构造表达式树的静态方法。
* 遍历表达式,若为操作数则构造单节点树压入stack,若为操作符,则弹出两个节点,与
* 操作符构造成新的树,再压入stack中。最后stack中只剩一个节点,该节点就是我们要求的
* 表达式树。
* @param expressions 后缀表达式分解过后的字符串数组
* @return 表达式树
*/
public static BinaryNode postfixToExpressionTree(String[] expressions){
BinaryNode operand1;     //用于暂存弹出的BinaryNode节点
BinaryNode operand2;
Stack<BinaryNode> stack = new Stack<BinaryNode>(); //用于构造表达式树的栈
for (String s:expressions) {   //遍历表达式
if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")){
operand1=stack.pop();  //弹出操作数
operand2=stack.pop();
stack.push(new BinaryNode(s,operand2,operand1)); //构造成新树并压入栈中
}else {
stack.push(new BinaryNode(s));
}

}
return stack.pop();
}


printBinaryTree(int depth,BinaryNode binaryNode)方法负责打印二叉树,并在每个节点前锁紧与深度相当的空格,方便观察树的结构。

/**
* 打印二叉树的方法。
* 通过递归调用来打印二叉树。并在节点前缩进了与深度相当的空格,方便观察。
* @param depth 当前节点在树中的的深度
* @param binaryNode 当前树节点
*/
public static void printBinaryTree(int depth,BinaryNode binaryNode){
for (int i=0;i<depth;i++){  //打印与深度相当的缩进
System.out.print("    ");
}
System.out.println(binaryNode.getElement());  //打印当前节点的数据
if (binaryNode.getLeft() != null){  //若左子树不为空,那么递归调用打印方法,打印左子树
printBinaryTree(depth+1,binaryNode.getLeft());
}
if (binaryNode.getRight() != null){  //若右子树不为空,那么递归调用打印方法,打印右子树
printBinaryTree(depth+1,binaryNode.getRight());
}

}


main()方法用于测试,负责接收表达式并将其拆解成字符串数组,传递给postfixToExpressionTree方法,然后调用printBinaryTree方法打印返回的表达式树。

/**
* 测试构造和打印表达式树的方法。
* main()方法用于测试,负责接收表达式并将其拆解成字符串数组,传递给
* postfixToExpressionTree方法,然后调用printBinaryTree方法打印返回的表达式树。
* @param args 忽略
*/
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();            //接收表达式
String[] splits= s.split("");  //分解成字符串数组
BinaryNode binaryNode=postfixToExpressionTree(splits);  //构造比表达式树
printBinaryTree(0,binaryNode); //打印表达式树
}


运行测试,输入ab+cde+**,输出结果为:

*
+
a
b
*
c
+
d
e


完整的实例已经分享到Github,项目地址:https://github.com/Dodozhou/Algorithm
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: