中缀表达式就是我们日常看到的数学表达式:比如(2+4)*2,对于人类来说很直观,但是对于计算机而言,这种表达式很不容易理解。于是就有了前缀表达式和后缀表达式。
前缀表达式
前缀表达式是指将操作符放在前面,然后再放置操作数,比如对前面表达式而言,前缀表达式为*、+、2、4、2;
后缀表达式
后缀表达式是指将先放操作数,然后再放操作符,比如对签名表达式而言,后缀表达式为2、4、+、2、*
可以总结出规律,前缀表达式和后缀表达式的操作符顺序是相反的,而操作数的顺序是相同的。
为什么计算机对后缀表达式(前缀)比较方便
我们看到前缀表达式中不存在诸如括号改变优先级的符号,事实上,通过前缀表达式和后缀表达式可以很容易构造一颗运算树,通过该运算树,可以使用递归的方式很方便计算表达式,比如该运算式构成的树为:
然后这里,只需要int leftVal = calculate(root.left);int rightVal = calculate(root.right);然后可以计算出root值。
前缀表达式转树
前缀表达式如何变成一颗运算树呢?
通过前缀表达式,从后向前遍历,当出现运算数时,将运算数变成Node对象压栈,当出现运算符时,弹出栈中前两个对象,然后再构成一颗子树,入栈。。看代码吧
package com.dacas.converter;
import java.util.Stack;
/**
* Created by dave on 2016/4/6.
*/
public class ConvertPrefixExpressionToTree implements IConverter {
@Override
public TreeNode convert(String expression) {
char[] chars = expression.toCharArray();
Stack<TreeNode> nodes = new Stack<>();
for(int i = chars.length-1;i>=0;i--){
TreeNode root = new TreeNode(chars[i]);
if(!isValid(chars[i])){
TreeNode top1 = nodes.pop();
TreeNode top2 = nodes.pop();
root.setLeftNode(top1);
root.setRightNode(top2);
}
nodes.push(root);
}
return nodes.size() == 1?nodes.pop():null;
}
}
后缀表达式转树
后缀表达式和前缀表达式构造树的方式非常类似。只是这次从前向后遍历。具体看代码
package com.dacas.converter; /**
* Created by dave on 2016/4/6.
*/
import java.util.Stack;
/**
* 将后缀表达式转换成一个表达式树
*/
public class ConvertPostExpressionToTree implements IConverter{
@Override
public TreeNode convert(String expression) {
Stack<TreeNode> nodes = new Stack<>();
char[] chars = expression.toCharArray();
for(char ch:chars){
TreeNode root = new TreeNode(ch);
if(!isValid(ch)) {
TreeNode top1 = nodes.pop();
TreeNode top2 = nodes.pop();
root.setLeftNode(top2);
root.setRightNode(top1);
}
nodes.push(root);
}
return nodes.size() == 1?nodes.pop():null;
}
}
中缀表达式转后缀表达式
- 使用两个栈,一个是操作符栈,一个是操作数栈;
- 遍历中缀表达式,当一个字符为操作数时,压入操作数栈;当为操作码时,如果操作码栈为空,直接压入,如果为(,直接压入操作码栈,如果字符为),则出栈到(位置处,当操作码栈不为空时,比较栈顶元素与当前元素的优先级,如果当前元素优先级小于等于栈顶元素,则出栈,否则入栈。
package com.dacas.converter;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
/**
* Created by dave on 2016/4/6.
* 将中缀表达式转换成后缀表达式
*/
public class ConvertMiddleExpressionToPostExpression{
static Map<Character,Integer> maps = new HashMap<>();
static {
maps.put('(',0);
maps.put('+',1);
maps.put('-',1);
maps.put('*',2);
maps.put('/',2);
}
public String convert(String midExpression){
Stack<Character> operators = new Stack<>();//操作符
Stack<String> operands = new Stack<>();//操作数
char[] chars = midExpression.toCharArray();
for(char ch:chars){
if(ch>='0' && ch<='9'){
operands.push(ch+"");
}else if(ch == '(') {
operators.push(ch);
}else if(ch == ')'){
char top;
while((top = operators.pop())!='('){
String ch1 = operands.pop();
String ch2 = operands.pop();
operands.push(ch2 + "," + ch1 + "," + top);
}
}else{//操作符
while (!operators.isEmpty() && comparePriority(operators.peek(), ch)) {//top >= ch,pop out
String ch1 = operands.pop();
String ch2 = operands.pop();
operands.push(ch2 + "," + ch1 + "," + operators.pop());
}
operators.push(ch);
}
}
while(!operators.isEmpty()){
String ch1 = operands.pop();
String ch2 = operands.pop();
operands.push(ch2+","+ch1+","+operators.pop());
}
return operands.pop();
}
private boolean comparePriority(char ch1,char ch2){
int int1 = maps.get(ch1);
int int2 = maps.get(ch2);
return int1 >= int2;
}
}
Main.java
import com.dacas.converter.*;
/**
* Created by dave on 2016/4/6.
*/
//数据结构与算法分析第4章
public class Main {
public static void main(String[] args) {
performConvertPostExpressionToTree();
}
private static void performConvertPostExpressionToTree(){
/***********后缀表达式转树***********/
String postfix = "ab+cde+**";
IConverter postConverter = new ConvertPostExpressionToTree();
TreeNode postNode = postConverter.convert(postfix);
System.out.println(postNode);
/************前缀表达式转树*****************/
String prefix = "-*+3456";
IConverter preConverter = new ConvertPrefixExpressionToTree();
TreeNode preNode = preConverter.convert(prefix);
System.out.println(preNode);
/****************中缀表达式转后缀表达式**********************/
String midfix = "3*(4+5/2-2*3/8)/2";
ConvertMiddleExpressionToPostExpression midConverter = new ConvertMiddleExpressionToPostExpression();
String postfixExpression = midConverter.convert(midfix);
System.out.println(postfixExpression);
String[] strs = postfixExpression.split(",");
String newString = "";
for(String tmp:strs){
newString+=tmp+"";
}
TreeNode postNode2 = postConverter.convert(newString);
System.out.println(postNode2);
}
}