1.分析:
使用两个栈,一个存入符号,一个存储中间结果。
遇到右括号,栈顶比它高或者同级的,去中间结果栈,所以可知,这个中间结果栈是只进不出。但是最后,pop出来的时候正好是后缀比表达式的逆序。所以,按照他的需求,我们在这里使用数组即可实现。这里引用尚硅谷老师的一张图作为说明:
2.代码思路:
- 先把字符串表达式转入数组集合中;(正则分割)
- 传入数组集合,开始转后缀(用到优先级比较)
- 后缀求值
代码:
package com;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class InfixToSuffix {
public static void main(String[] args) {
String expression="1+9*5-1";
List<String> list = toInfixExpression(expression);
List<String> suffixExpression = SuffixExpression(list);
System.out.println(suffixExpression);
int calculate = SuffixDemo.calculate(suffixExpression);
System.out.println(calculate);
}
//1.直接操作字符串不方便,所以先把他存入到数组中
//2.在把数组中的顺序,转为后缀顺序
public static List<String> SuffixExpression(List<String> list){
//定义两个栈,由于一个只进不出,所以使用数组代替
Stack<String> s1=new Stack<>(); //符号栈
List<String> s2=new ArrayList<>();
//遍历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());
}
}else{
//当item优先级小于栈顶优先级时,依次弹出加入s2
//编写一个类,可以返回优先级高低
while(s1.size()!=0&&Priority.getValue(s1.peek())>=Priority.getValue(item) )
{
s2.add(s1.pop());
}
s1.push(item);
}
}
//将s1剩余操作符弹出加入s2
while(s1.size()!=0){
s2.add(s1.pop());
}
return s2;
}
//将中缀表达式转成对应的List
public static List<String> toInfixExpression(String s)
{
//定义容器
List <String> ls=new ArrayList<String>();
int i=0; //这里是一个指针,用于遍历字符串
String str;
char c;
while(i<s.length())
{
//如果是字符(ASII码:48-57——0-9)
if((c=s.charAt(i))<48||((c=s.charAt(i))>57)){
ls.add(""+c);
i++;
}else{
str="";
while(i<s.length()&&(c=s.charAt(i))>=48&&((c=s.charAt(i))<=57)){
str+=c; //拼接字符串
i++;
}
ls.add(str);
}
}
return ls;
}
}
class Priority{
private static int ADD=1;
private static int SUB=1;
private static int MUL=2;
private static int DIV=2;
//写一个方法,返回对应的优先级数字
public static int getValue(String str){
int result=0;
switch(str){
case "+":
result=ADD;
break;
case "-":
result=SUB;
break;
case "*":
result=MUL;
break;
case "/":
result=DIV;
break;
default:
System.out.println("不存在此运算符");
break;
}
return result;
}
}
后缀表达式求值:
package com;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class SuffixDemo {
public static void main(String[] args) {
//[1, 2, 3, +, 4, *, 5, -, (, (, +]
//4 5 * 8 - 60 + 8 2 / +
String suffixExpression="1 9 5 * + 1 -";
List<String> list=getListString(suffixExpression);
System.out.println("结果是:"+list);
int res=calculate(list);
System.out.println("计算结果是:"+res);
}
//后缀表达式
//1.使用空格分隔开,加到数组中
public static List<String> getListString(String suffixExpression){
//按照空格将suffixExpression分割
String[] split=suffixExpression.split(" ");
List<String> list=new ArrayList<String>();
for(String elem:split)
{
list.add(elem);
}
return list;
}
//完成逆波兰表达式
public static int calculate(List<String> list){
//创建一个栈,只需要一个栈即可
Stack<String> stack=new Stack<String>();
//遍历
for(String item:list){
//使用正则表达式来取出数字
if(item.matches("\\d+")) //\表示转义,\d表示数,+表示多位
{
//入栈
stack.push(item);
}
else{
//pop出栈出两个数,进行运算
int num1=Integer.parseInt(stack.pop());
int num2=Integer.parseInt(stack.pop());
int res=0;
if(item.equals("+")){
res=num1+num2;
}else if(item.equals("-")){
res=num2-num1;
}else if(item.equals("*")){
res=num1*num2;
}else if(item.equals("/")){
res=num2/num1;
}else {
throw new RuntimeException("运算符有错误");
}
stack.push(""+res) ; //???数字转字符串
}
}
return Integer.parseInt(stack.pop());
}
}