逆波兰表达式的生成(Java版)
逆波兰表达式又叫做后缀表达式。
正常表达 | 逆波兰表达 |
---|---|
a+b | a,b,+ |
a+(b-c) | a,b,c,-,+ |
网上很多的转换逆波兰表达式的代码都使用了太多了for, if, 还有各种char之间的比较,读起来非常的累人。
在逆波兰表达式中比较麻烦的一步就是比较各个运算符之间的优先级关系
() > */ > +-
括号 (大于) 乘除 (大于) 加减
网上的很多方法是通过判断字符的ASCII码来判断运算符的优先级。
对应的ASCII码表如下:
+ 43
- 45
* 42
/ 47
( 40
) 41
可以看出除法的ASCII码值是47,但是他的优先级确又高过加法和减法。
因此我们创建一个内部类,来定义每个操作符的优先级。
/**
* 内部类
* content包含具体的字符信息
* priority 定义了运算符的优先级
*/
private static class Element{
private Character content;
private int priority;
public Element() {
}
public Character getContent() {
return content;
}
public void setContent(Character content) {
this.content = content;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
@Override
public String toString() {
return content + " ";
}
}
对于具体的逆波兰表达式的生成的核心代码如下
定义好一个存放最终表达式结果的List,以及一个存放操作符和左右括号的栈(Stack)
//读到的是操作符(+-*/)(记为read),将其与栈顶的操作符(记为top)进行优先级比较:
// 如果read>top,read入栈,继续读下一个;read≤top,top出栈,并输出到list中,read继续和新的top比较;
// top为空,read直接入栈;若top是“(”,read直接入栈,因为“(”优先级最高;
private void processOperator(Element read, List<Element> list, Stack<Element> operations){
if(operations.isEmpty()){
operations.push(read);
return;
}
Element tmp = operations.peek();
if(read.getPriority()>tmp.getPriority()){
operations.push(read);
}else{
list.add(operations.pop());
processOperator(read, list, operations);
}
}
完整代码如下
package java_data_structure;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* 参考 http://blog.csdn.net/bruce_6/article/details/39205837
*
* @author Junying Li
*/
public class ReversePolishExpression {
/**
* 内部类
* content包含具体的字符信息
* priority 定义了运算符的优先级
*/
private static class Element{
private Character content;
private int priority;
public Element() {
}
public Character getContent() {
return content;
}
public void setContent(Character content) {
this.content = content;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
@Override
public String toString() {
return content + " ";
}
}
public static void main(String[] args){
//[6 , 5 , 2 , 3 , + , 8 , * , + , 3 , + , * ]
String expression = "6*(5+(2+3)*8+3)";
// String expression = "a+(b-c)*d";
ReversePolishExpression instance = new ReversePolishExpression();
List<Element> result = instance.convertExpressionToReversePolish(expression);
System.out.print(result);
}
public List<Element> convertExpressionToReversePolish(String expression){
//将字符串表达式转换成一个List,定义好其中的算术表达符的优先级
List<Element> preparedElementsList = prepareElementsList(expression.toCharArray());
List<Element> resultList = new ArrayList<>();
Stack<Element> operatorStack = new Stack<>();
for(Element e : preparedElementsList){
Character c = e.getContent();
switch (c){
case '+':
processOperator(e, resultList, operatorStack);
break;
case '-':
processOperator(e, resultList, operatorStack);
break;
case '*':
processOperator(e, resultList, operatorStack);
break;
case '/':
processOperator(e, resultList, operatorStack);
break;
case '(':
operatorStack.push(e);
break;
case ')':
for(int i=0; i<operatorStack.size(); i++){
Element x = operatorStack.peek();
if(x.getContent()!='('){
resultList.add(operatorStack.pop());
}else {
operatorStack.pop();
break;
}
}
break;
default:
resultList.add(e);
}
}
while (!operatorStack.isEmpty()){
resultList.add(operatorStack.pop());
}
return resultList;
}
//
private List<Element> prepareElementsList(char[] chars){
List<Element> list = new ArrayList<>();
for(char c : chars){
Element element = new Element();
element.setContent(c);
if(c == '+' || c == '-'){
element.setPriority(1);
}else if(c == '*' || c == '/'){
element.setPriority(2);
}
list.add(element);
}
return list;
}
//读到的是操作符(+-*/)(记为read),将其与栈顶的操作符(记为top)进行优先级比较:
//read>top,read入栈,继续读下一个;read≤top,top出栈,并输出到list中,
// read继续和新的top比较;top为空,read直接入栈;若top是“(”,read直接入栈,因为“(”优先级最高;
private void processOperator(Element read, List<Element> list, Stack<Element> operations){
if(operations.isEmpty()){
operations.push(read);
return;
}
Element tmp = operations.peek();
if(read.getPriority()>tmp.getPriority()){
operations.push(read);
}else{
list.add(operations.pop());
processOperator(read, list, operations);
}
}
}