中缀表达式转后缀表达式
原创
©著作权归作者所有:来自51CTO博客作者wx63451a3b20abb的原创作品,请联系作者获取转载授权,否则将追究法律责任
首先要明确步骤
1.初始化两个栈:运算符栈s1和储存中间结果的栈s2
2.从左至右扫描中缀表达式
3.遇到操作数时,将其压s2
4.遇到运算符时,比较其与s1栈顶运算符的优先级
- 4.1.如果s1为空,或栈顶运算符为左括号
“(”
,则直接将此运算符入栈s1 - 4.2.若优先级比s1栈顶运算符的高,也将运算符压入s1
- 4.3.若优先级比s1栈顶运算符的低,则将s1栈顶的运算符弹出并压入到s2中,再次转到4.1与s1中新的栈顶运算符相比较
5.遇到括号时:
- 5.1如果是左括号
“(”
,则直接压入s1 - 5.2如果是右括号
“)”
,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
6.重复步骤2至5,直到表达式的最右边
7.将s1中剩余的运算符依次弹出并压入s2
8.依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式
需要说明的一点
这里的栈s2,只是起到了储存中间结果的作用,在计算的过程中未参与运算,只是最后依次出栈,而且还需要逆序输出。与其这样,还不如直接用一个List
集合来代替Stack
,直接正序输出就好了
代码
public class Main {
public static void main(String[] args) {
List<String> list = getList("1+((2+3)*4)-5");
for (String s: list){
System.out.print(s+",");
}
System.out.println("------------------");
List<String> strings = parseToPostfixExpression(list);
for (String s: strings){
System.out.print(s+",");
}
}
//将中缀表达式转化为后缀表达式
public static List<String> parseToPostfixExpression(List<String> infixExpression){
//操作数栈
Stack<String> s1 = new Stack<>();
//装最后结果的集合
ArrayList<String> s2 = new ArrayList<>();
for (String item:infixExpression){
if (item.matches("\\d+")){
//是数字,则直接加入s2中
s2.add(item);
}else if (item.equals("(") || s1.size() == 0){
//是左括号,或者s1为空,直接加入s1中
s1.push(item);
}else if (item.equals(")")){
//是右括号,则将s1中元素依次加入s2中,直到遇到左括号,并且最后扔掉左括号
while (s1.size() > 0 && !s1.peek().equals("(")){
//当s1有元素且s1最上面的元素不是左括号的时候,依次加入s2
s2.add(s1.pop());
}
//直接弹出左括号
s1.pop();
}else {
//是运算符,需要比较优先级
//当item优先级比s1栈顶的低的时候,需要将s1栈顶的运算符弹出,加到s2中,并将新栈顶与item比较,重复此操作
//一定要注意,这里s1.size() > 0 的判断要在前面,否则可能报错,因为s1.peek()可能是空的
while (s1.size() > 0 && priority(item.charAt(0)) <= priority(s1.peek().charAt(0)) ){
s2.add(s1.pop());
}
//比较完毕后,将item加到s1中
s1.push(item);
}
}
//依次将s1中剩下的操作符加到s2中
while (s1.size() > 0){
s2.add(s1.pop());
}
return s2;
}
//将表达式转化为List集合
public static List<String> getList(String expression){
//首先创建集合
List<String> numsAndOpers = new ArrayList<>();
//创建索引和多位数变量
int index = 0;
String realNum = "";
while (index < expression.length()){
if ((expression.charAt(index) < 48) || (expression.charAt(index) >57)){
//说明是符号 则直接加入集合
numsAndOpers.add(""+expression.charAt(index));
index++;//注意index++的位置
}else {
//说明是数字,得考虑多位数的情况
realNum = "";//先清空下上次的残留
while (index < expression.length() && (expression.charAt(index) >= 48) && (expression.charAt(index) <= 57)){
realNum = realNum + expression.charAt(index);
index++;//注意index++的位置,index直接就跟着变了,无需再设置另外一个变量
}
numsAndOpers.add(realNum);
}
}
return numsAndOpers;
}
//返回运算符的优先级,这个优先级是程序员自己定的
public static int priority(int oper){
if (oper == '*' || oper == '/'){
return 1;
}else if (oper == '+' || oper == '-'){
return 0;
}else {
return -1;//异常情况
}
}
}