具体步骤
(1)初始化两个栈:运算符栈s1和存储中间结果的栈s2;
(2)从左至右扫描中缀表达式;
(3)遇到操作数时,将其压入s2;
(4)遇到运算符时,比较其与s1栈顶运算符的优先级;
1、如果s1为空,或栈顶运算符为左括号“(” ,则直接将此运算符入栈
2、否则,若优先级比栈顶运算符高,也将运算符压入s1
3、否则,将s1栈顶的运算符弹出并压入到s2中,再转入4.1 与s1中新的栈顶运算符相比较
(5)遇到括号时:
1.如果是左括号“(” ,则直接压入s1
2.如果是右括号 “)” ,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止
(6)重复步骤2至5,直到表达式的最右边
(7)将s1中剩余的运算符依次弹出并压入s2
(8)依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式
eg:比如中缀表达式:“1+((2+3)×4)-5” 转换为后缀表达式为:“1 2 3 + 4 * + 5 - ”
代码实现
package database;
import data.O;
import dataone.S;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class PolandNotation {
public static void main(String[] args) {
//定义一个逆波兰表达式 (3+4)*5-6
/* String nblexpresion ="3 4 + 5 * 6 -";
List<String> nlist=getlistString(nblexpresion);
System.out.println(nlist);
int res =charters(nlist);
System.out.println(res);*/
//中缀表达式转后缀
String hzexpresion ="1+((2+3)*4)-5";
List<String> list = toInfixExpresion(hzexpresion); //将表达式存入一个list集合中
System.out.println(list);
List<String> list1 = lastExpresion(list);//将中缀表达式转为后缀表达式具体实现
System.out.println(list1);
int charters = charters(list1);//计算表达式的值
System.out.println(charters);
}
//将中缀转后续具体实现方法
public static List<String> lastExpresion(List<String> list){
//定义两个栈
Stack<String> s1 =new Stack<String>();//符号栈
List<String> s2 =new ArrayList<String>();//转换,并没pop() 后面还需逆序输出,所以用链表
//遍历list
for (String item:list
) {
if (item.matches("\\d+")){
s2.add(item);
}else if (item.equals("(")){
s1.push(item);
}else if (item.equals(")")) {
//如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
while(!s1.peek().equals("(")) {
s2.add(s1.pop());
}
s1.pop();
}else {
while (s1.size()!=0&&Operation.getValues(s1.peek())>= Operation.getValues(item)){
s2.add(s1.pop());
}
s1.push(item);
}
}
//将s1中剩余元素压入s2中
while (s1.size()!=0){
s2.add(s1.pop());
}
return s2;
}
//中缀转后缀方法
public static List<String> toInfixExpresion(String s){
List<String> list =new ArrayList<>();
int i=0;//定义一个指针
String str; //多位数拼接
char c; //遍历一个字符 存入c
do {
//如果为非数字,则加入list
if ((c=s.charAt(i))<48||(c=s.charAt(i))>57){
list.add(""+c);
i++;
}else {
//如果是数字,需要考虑多位数
str="";
while ((i<s.length())&&(c=s.charAt(i))>=48&&(c=s.charAt(i))<=57){
str+=c;
i++;
}
list.add(str);
}
}while (i<s.length());
return list;
}
public static List<String> getlistString(String nblexpresion){
//将表达式分割
String split[] = nblexpresion.split(" ");
//保存进入一个集合
List<String> list =new ArrayList<>();
for (String ele: split
) {
list.add(ele);
}
return list;
}
//传递方法 遍历 入栈 运算 出栈 再入栈
public static int charters (List<String> lis){
Stack<String> stack =new Stack<String>();
for (String s:lis
) {
if (s.matches("\\d+")){
stack.push(s);
}else {
//pop出两个数,且进行计算,再入栈
int num1= Integer.parseInt(stack.pop());
int num2 =Integer.parseInt(stack.pop());
int res=0;
if (s.equals("+")){
res=num1+num2;
}else if (s.equals("-")){
res=num2-num1;
}else if (s.equals("*")){
res=num1*num2;
}else if (s.equals("/")){
res=num2/num1;
}else {
throw new RuntimeException("运算符有误");
}
//入栈的res就是结果
stack.push(res+"");
}
}
return Integer.parseInt(stack.pop());
}
}
//写一个类,返回一个运算符的优先级
class Operation{
private static int ADD =1;
private static int SUB =1;
private static int MUL =2;
private static int DEL =2;
//写一个方法,返回对应的优先级的值
public static int getValues(String num){
int result =0;
switch (num){
case "+":
result=ADD;
break;
case "-":
result=SUB;
break;
case "*":
result=MUL;
break;
case "/":
result=DEL;
break;
default:
break;
}
return result;
}
}