中缀表达式转后缀表达式步骤: 1.初始化一个栈,用于保存 暂时还不能确定运算顺序的运算符 2.扫描各个元素 2.1遇到操作数,直接加入后缀表达式 2.2遇到界限符 2.2.1 遇到“(”,直接压入栈 2.2.2 遇到“)”,依次弹出栈内运算符并加入后缀表达式,直到弹出“(”为止, “(”不加入后缀表达式 2.3遇到运算符,依次弹出栈中优先级高于或等于当前运算符的所有运算符,并加入后缀表达式 若遇到“(”或者栈空则停止,之后再把当前运算符入栈(即若栈为空或栈顶为“(”,则将运算符压入栈中) 3.遍历完之后将剩余的运算符加入后缀表达式
后缀表达式计算: 1.从左到右扫描下一个元素,知道处理完所有元素 2.若扫描到操作数则压入栈 并继续扫描(回到1) 3.若扫描到运算符,则弹出两个栈顶元素 执行相应的运算 运算结果压回栈顶 继续扫描
中缀转后缀仅包含加减乘除和“(”,“)”,不包含小数点,空格,特殊字符。
后缀表达式计算每个字符间均含有空格。
代码:
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class PolandNotion {
public static void main(String[] args) {
String expression = "12+21*3/(4-1)";
List<String> list = toInfixExpression(expression);
System.out.println(list);
String houzhui = transform(list);
System.out.println(houzhui);
List<String> listString = getListString(houzhui);
int res = calculate(listString);
System.out.println(res);
}
//将一个逆波兰表达式,依次将数据和运算符 放入ArrayList当中
public static List<String> getListString(String expression){
//将表达式分割,,其实我也不知道为啥要空格分割定的时候
String[] split = expression.split(" ");
List<String> list = new ArrayList<>();
for (String elme:split){
list.add(elme);
}
return list;
}
//对逆波兰表达式的计算
public static int calculate(List<String> ls){
//创建栈
Stack<String> stack = new Stack<>();
//遍历ls
for (String item:ls){
//使用正则表达式来取出
if (item.matches("\\d+")){//匹配多位数
//直接入栈
stack.push(item);
}else {
//如果不是数字而是运算符,则pop出两个数,运算并入栈
int num2 = Integer.parseInt(stack.pop());
int num1 = Integer.parseInt(stack.pop());
int res = 0;
if (item.equals("+")){
res = num1 + num2;
}else if (item.equals("-")){
//让栈下面的数减去上面的数字
res = num1 - num2;
}else if (item.equals("*")){
res = num1 * num2;
}else if (item.equals("/")){
res = num1/num2;
}else {
throw new RuntimeException("运算符有误");
}
//运算完之后将结果入栈 转成字符串
stack.push(""+res);
}
}
//最后留在stack中的数据就是运算结果
return Integer.parseInt(stack.pop());
}
//将一个中缀表达式 转成对应的list 用list好操作
public static List<String> toInfixExpression(String s){
//定义一个list 存放中缀表达式对应的数据
List<String> ls=new ArrayList<String>();
//指针 用于遍历中缀字符串
int i=0;
String str; //做对多位数的拼接工作
char c; //每遍历到一个字符就放入c
do {
//若果c是一个非数字,就需要加入到qq
if( (c=s.charAt(i)) <48 || (c=s.charAt(i)) >57){
ls.add(""+c);
i++; //需要后移
}else{
//如果是一个数,需要考虑多位数的问题
StringBuilder strBuilder = new StringBuilder();//制成空字符串
while (i<s.length()&&(c= s.charAt(i))>=48&&(c= s.charAt(i))<=57){
strBuilder.append(c);//拼接
i++;
}
str = strBuilder.toString();
ls.add(str);
}
}while (i<s.length());
return ls;
}
public static String transform(List<String> ls){
Stack<String> stack = new Stack<>();
String biaodashi = "";
for (String item:ls){
if (item.matches("\\d+")){
biaodashi = biaodashi.concat(item+" ");
} else if (item.equals("(")){
stack.push(item);
}else if (item.equals(")")){
while (true){
String s = stack.pop();
if (!s.equals("(")){
biaodashi = biaodashi.concat(s+" ");
}else {
break;
}
}
}else if (isOper(item)){
while (true) {
if (stack.empty() || stack.peek().equals("(")) {
stack.push(item);
break;
} else if (priority(item) > priority(stack.peek())) {
stack.push(item);
break;
} else if (priority(item) <= priority(stack.peek())) {
String s = stack.pop();
biaodashi = biaodashi.concat(s + " ");
}
}
}
}
//遍历完之后将剩余的运算符加入后缀表达式
while (stack.size()!=0){
biaodashi = biaodashi.concat(stack.pop()+" ");
}
return biaodashi;
}
private static boolean isOper(String val) {
return val.equals("+") || val.equals("-") || val.equals("*") || val.equals("/");
}
//返回运算符的优先级
//优先级使用数字来表示,数字越大,优先级越高
public static int priority(String oper){
if (oper.equals("*") || oper.equals("/")){
return 1; //如果符号为乘除,则认为优先级为1
}else if(oper.equals("+") || oper.equals("-")){
return 0;
}else {
return -1; //假定目前的计算式只有加减乘除
}
}
}
运行结果:
[12, +, 21, *, 3, /, (, 4, -, 1, )]
转成后缀表达式为:12 21 3 * 4 1 - / +
运算结果为:33