代码思路:
原运算式每个字符通过过空格间隔
构造一个建立运算符优先级大小的函数(priority),通过返回int型建立运算符之间的优先级。
将运算式以空格切割转换为数组并依次添加至一个ArrayList数组(list)
因为栈的特性为先入后出,若作为中缀表达式返回,还需倒序,且方法中只需一个栈储存运算符,所以用ArrayList(endList)储存转换后的结果
建立字符栈 operStack做字符中转用处
遍历list
1.若为数字,直接插入到endList中
2.若为运算符:当operStack为空或遍历字符为( 时直接添入栈中
2.1 若运算符为 )时,循环从字符栈中出栈并且添加到endList中,直到循环字符为"(",停止且丢弃"("
.2若运算符为 +,—,*,/,拿出栈顶字符,通过priority函数做对比,得出优先级。注:出栈运算符要优先回栈,后添加待入栈运算符.(或写方法拿到顶栈值)
2.2.1当拿出的是( 时,不做比较。
2.2.2当待入栈运算符大于或等于出栈运算符时,先返回出栈运算符后将待入栈运算符添加到字符栈中
2.2.3反之将出栈运算符返回栈中,带入栈运算符添加入endList中
3 遍历结束后,将运算符栈中剩下的元素依次添加至endList中
4 返回endList
5构造函数calculate来计算后缀表达式,建立numStack存放数字
6endList传入calculate函数,遍历endList,
6.1若为数字,直接入栈
6.2若为运算符,出栈两个数,与·运算符计算,将结果再次入栈。注:因为栈先入后出的特性,减法和除法,应当是后出栈数在前,先出栈数在后
6.3遍历结束后。栈中只存在一个数,该数为答案。
eg:还是个大学生,总结自己学习内容所用,大佬们勿喷。
代码如下:
import java.util.ArrayList;
import java.util.Stack;
public class PolandNotationAPP {
public static void main(String[] args) {
// TODO 自动生成的方法存根
String str="1 + ( ( 2 + 3 ) * 4 ) - 5";
ArrayList<String> list=parseSuffixExpreesionList(str);
System.out.printf("后缀表达式为:");
for(String value:list) {
System.out.printf(value+" ");
}
int result=calculate(list);
System.out.println("\n最后结果为:"+result);
}
public static ArrayList<String> parseSuffixExpreesionList(String str){//中缀表达式转后缀表达式
ArrayList<String> endList=new ArrayList<String>();//用list存放结果
Stack<String> operStack=new Stack<String>();//存放运算符的栈
String[] temp=str.split(" ");//字符串转换为数组
ArrayList<String> list=new ArrayList<String>();
for(int i=0;i<temp.length;i++) {//将字符数组遍历添加到一个list中
list.add(temp[i]);
}
for(String value:list) {
if(value.matches("\\d+")) {//正则表达式判断是否为数字
endList.add(value);//如果是数字直接添加到endList中
}else {//如果是字符
if(operStack.empty()||value.equals("(")) {//字符栈为空或字符为"("时,直接添加到字符栈中
operStack.push(value);
}else if(value.equals(")")) {//字符为")"时,循环从字符栈中出栈并且添加到endList中,直到循环
while(true) { //字符为"(",停止且丢弃"("
String stringTemp=operStack.pop();
if(stringTemp.equals("(")) {
break;
}
endList.add(stringTemp);
}
}else {//当为运算符时,通过自写函数priority,比较优先级,当出栈运算符为:")"时,不做比较,直接添加
String stringTemp=operStack.pop();//注:出栈运算符要优先回栈,后添加待入栈运算符.(或写方法拿到顶栈值)
int num1=priority(value);
int num2=priority(stringTemp);
if(num2==-1) {//出栈运算符为:")"
operStack.push(stringTemp);
operStack.push(value);
continue;
}
if(num1>=num2) {//当待入栈运算符大于或等于出栈运算符时,先返回出栈运算符后将待入栈运算符添加到字符栈中
operStack.push(stringTemp);
operStack.push(value);
}else {//反之将出栈运算符返回栈中,带入栈运算符添加入endList中
operStack.push(stringTemp);
endList.add(value);
}
}
}
}
while(!operStack.empty()) {//将运算符栈中剩下的元素依次添加至endList中
endList.add(operStack.pop());
}
return endList;
}
public static int priority(String oper) {//通过返回数字建立优先级
if(oper.equals("*")||oper.equals("/")) {
return 1;
}else if(oper.equals("+")||oper.equals("-")){
return 0;
}else if(oper.equals("(")) {
return -1;
}else {
System.out.println(oper);
throw new RuntimeException("符号有问题");
}
}
public static int calculate(ArrayList<String> list) {
Stack<String> numStack=new Stack<String>();
for(String value:list) {
if(value.matches("\\d+")) {//正则表达式判断是否为数字
numStack.push(value);
}else {//如果是运算符,出栈两个数字,做运算,运算结果添加到数字栈中
int num2=Integer.parseInt(numStack.pop());//因为栈先入后出的特性,减法和除法,应当是后出栈数在前,先出栈数在后
int num1=Integer.parseInt(numStack.pop());
int temp=0;
if(value.equals("+")) {
temp=num1+num2;
}else if(value.equals("-")) {
temp=num1-num2;
}else if(value.equals("*")) {
temp=num1*num2;
}else if(value.equals("/")) {
temp=num1/num2;
}else {
System.out.println("运算符错误");
}
numStack.push(""+temp);
}
}
return Integer.parseInt(numStack.pop());//此时栈中唯一的数字就是运算答案
}
}
运算结果为: