表达树—构建表达式树、获取表达式(二)
回顾二叉树的递归遍历
- 前序遍历:访问根结点-->前序遍历根结点的左子树-->前序遍历根结点的右子树。
- 中序遍历:中序遍历根结点的左子树-->访问根结点-->中序遍历根结点的右子树。
- 后序遍历:后序遍历根结点的左子树-->后序遍历根结点的右子树-->访问根结点。
二叉树递归遍历获得表达式
假设,已知中缀表达式为:(A+B*C)/D,需要获得前缀表达式,后缀表达式。
总结:表达树的前序遍历为前缀表达式,中序遍历为中缀表达式,后续遍历为后缀表达式。
- 前缀表达式(前序遍历):/+A*CBD。
- 中缀表达式(中序遍历):A+B*C/D。
- 后缀表达式(后序遍历):ACB*+D/。
利用后缀表达式构建表达式树
后缀表达式:ACB*+D/。
算法思想:
- 依次读取字符。
- 如果该符号是操作数,创建操作数结点并且入栈。
- 如果该符号为操作符,把栈顶T1、T2相继出栈,创建操作符结点,操作符结点的左右孩子分别为T1、T2,最后把操作符结点入栈。
Java代码实现构建过程
二叉链表结构
//二叉树节点
public class BinaryTreeNode {
private int data;
private BinaryTreeNode left;
private BinaryTreeNode right;
}
算法实现
public class ExprTree {
//最后访问头结点
public BinaryTreeNode buildExprTree(char postfixExpr[],int size){
LinkedList<BinaryTreeNode> stack=new LinkedList();
BinaryTreeNode node=null;
for(int i=0;i<size;i++){
if(isOperateNum(postfixExpr[i])){
node=new BinaryTreeNode();
node.setLeft(null);
node.setRight(null);
node.setData(postfixExpr[i]);
stack.push(node);
}else{
BinaryTreeNode leftChild=stack.pop();
BinaryTreeNode rightChild=stack.pop();
node =new BinaryTreeNode();
node.setLeft(leftChild);
node.setRight(rightChild);
node.setData(postfixExpr[i]);
stack.push(node);
}
}
return stack.getLast();
}
//判断是否是操作数
private boolean isOperateNum(char c){
if(c=='/'||c=='+'||c=='*'||c=='-'){
return false;
}
return true;
}
}
发散思考-更进一步
- 我们肯定会思考,为什么选用后缀表达式构建?而不选择前缀表达式、后缀表达式呢?源于各表达式结构,采用后缀表达式更容易实现构建。
- 如果已知前缀表达式、中缀表达式,怎么办呢?曲线救国,先把前缀表达式、中缀表达式转换成后缀表达式去构建,否则只能利用栈的相关算法实现。
- 总结:所有的解决方案没有独步天下,只有适合某一个场景下。若碰见前缀表达式,求其他中缀、后缀,那就用栈的算法实现吧。
- 利用栈转换表达式参考:http://www.cnblogs.com/qiuyong/p/6790290.html