1.逆波兰表达式(后缀表达式)的计算过程:
2.思路分析:
3.逆波兰计算器(只处理整数)代码实现:
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class PolandNotation {
public static void main(String[] args) {
//定义逆波兰表达式
//(30+4)×5-26 => 30 4 + 5 × 26 -,使用空格隔开
//4*5-8+60+8/2 => 4 5 * 8 - 60 + 8 + 2 /
String suffixExpression="4 5 * 8 - 60 + 8 2 / +";
//1.先将"3 4 + 5 × 6 -"放到ArrayList中;
//2.将ArrayList传递给方法,遍历数组,配合栈完成计算
List rpnList=getListString(suffixExpression);
System.out.println("rpnList= "+rpnList);
int res=calcute(rpnList);
System.out.println("计算的结果是= "+res);
}
//将逆波兰表达式依次将数据和运算符放入到ArrayList中
public static List getListString(String suffixExpression){
String[] split=suffixExpression.split(" ");
List list=new ArrayList();
for(String ele:split) {
list.add(ele);
}
return list;
}
//完成对逆波兰表达式的运算,对List进行遍历
public static int calcute(List ls) {
//创建栈
Stack 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("运算符有误");
}
//把结果res入栈
stack.push(""+res);//将整型转为string
}
}
//最后留在stack中的数据是运算结果
return Integer.parseInt(stack.pop());
}
}
4.中缀表达式转换为后缀表达式
5.中缀表达式转后缀表达式代码实现
//方法:将中缀表达式转化为对应的list
public static List toInfixExpressionList(String s){
List ls=new ArrayList();
int i=0;//用于遍历中缀表达式字符串s的指针
String str;//用于对多位数拼接
char c;//每遍历到一个字符,放入到c
do {
//如果c是非数字,加入到ls中
if((c=s.charAt(i))<48 || (c=s.charAt(i))>57){
ls.add(""+c);
i++;//i后移
}else {//数字考虑多位数的问题
str="";//将str置空
while(i=48 && (c=s.charAt(i))<=57 ) {
str+=c;//拼接
i++;
}
ls.add(str);
}
}while(i
class Operation{
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 operation) {
int result=0;
switch (operation) {
case "+":
result=ADD;
break;
case "-":
result=SUB;
break;
case "*":
result=MUL;
break;
case "/":
result=DIV;
break;
case "(":
break;
case ")":
break;
default:
throw new RuntimeException("运算符输入错误");
}
return result;
}
}
public static List parseSuffixExpressionList(List ls){
//定义两个栈
Stack s1=new Stack();//符号栈
//s2在算法中没有pop操作,且需要逆序输出,故可以不用s2栈而用ArrayList更简单操作
// Stack s2=new Stack();//储存中间结果的栈
List s2=new ArrayList();//存储中间结果的List
//遍历ls
for(String item:ls) {
if(item.matches("\\d+")) {//如果是数,加入s2
s2.add(item);
}else if(item.equals("(")) {//左括号直接入栈s1
s1.push(item);
}else if(item.equals(")")) {
//如果是右括号,依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将一对括号丢弃
while(!s1.peek().equals("(")) {
s2.add(s1.pop());
}
s1.pop();//重要,将"("丢弃,消除括号
}else {
//若item的优先级小于等于s1栈顶运算符的优先级,将s1栈顶的运算符弹出并加入到s2中,再将item与s1栈顶运算符比较
//问题:缺少比较优先级高低的方法
while(s1.size()!=0 && Operation.getValue(s1.peek()) >= Operation.getValue(item)) {
s2.add(s1.pop());
}
//最后将item压入s1栈
s1.push(item);
}
}
//将s1中剩余的运算符加入到s2中
while(s1.size()!=0) {
s2.add(s1.pop());
}
return s2;//s2是list,输出的顺序就是存入的顺序,即后缀表达式的正确顺序
}
public static void main(String[] args) {
String expression="1+((2+3)*4+5)/5-5";
List infixExpressionList=toInfixExpressionList(expression);
System.out.println("中缀表达式转为为list= "+infixExpressionList);
List suffixExpressionList=parseSuffixExpressionList(infixExpressionList)
System.out.println("后缀表达式对应的list= "+suffixExpressionList);
System.out.printf("expression: %s=%d",expression,calcute(suffixExpressionList));
System.out.println();
}
6.逆波兰计算器的完整版
package stack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
import java.util.regex.Pattern;
public class ReversePolandMultiCalc {
//匹配 + - * / ()运算符
static final String SYMBOL="\\+|-|\\*|/|\\(|\\)";
static final String LEFT="(";
static final String RIGHT=")";
static final String ADD="+";
static final String MINUS="-";
static final String TIMES="*";
static final String DIVISION="/";
static final int LEVEL_01=1;
static final int LEVEL_02=2;
static final int LEVEL_HIGH=Integer.MAX_VALUE;
static Stack stack=new Stack<>();
static List data=Collections.synchronizedList(new ArrayList());
//方法:去除所有空白符
public static String replaceAllBlank(String s) {
//\\s+匹配任何空白字符,包括空格、制表符、换页符等
return s.replace("\\s+", "");
}
//方法:判断是不是数字 int double long float
public static boolean isNumber(String s) {
Pattern pattern=Pattern.compile("^[-\\+]?[.\\d]*$");
return pattern.matcher(s).matches();
}
//方法:判断是否是运算符
public static boolean isSymbol(String s) {
return s.matches(SYMBOL);
}
//方法:匹配运算等级
public static int calcLevle(String s) {
if("+".equals(s)||"-".equals(s)) {
return LEVEL_01;
}else if("*".equals(s)||"/".equals(s)) {
return LEVEL_02;
}
return LEVEL_HIGH;
}
//方法:匹配
public static List doMatch(String s) throws Exception{
if(s==null||"".equals(s.trim())) {
throw new RuntimeException("data is empty");
}
if(!isNumber(s.charAt(0)+"")) {
throw new RuntimeException("data is illeagle,start not with a number");
}
s=replaceAllBlank(s);
System.out.println("表达式字符串:"+s);
String each;
int start=0;
for(int i=0;icalcLevle(stack.peek())) && calcLevle(each)=calcLevle(stack.peek())) {
if(LEVEL_HIGH==calcLevle(stack.peek())) {
stack.pop();
break;
}
data.add(stack.pop());
}
}
start=i;//前一个运算符的位置
}else if(i==s.length()-1 ||isSymbol(s.charAt(i+1)+"")) {
each=start==0?s.substring(start,i+1):s.substring(start+1,i+1);
if(isNumber(each)) {
data.add(each);
continue;
}
throw new RuntimeException("data not match number");
}
}
//如果栈中还有元素,元素需要依次出栈入列
Collections.reverse(stack);
data.addAll(new ArrayList<>(stack));
System.out.println(data);
return data;
}
//方法:运算
public static Double doTheMath(String s1,String s2,String symbol) {
Double result;
switch(symbol) {
case ADD:
result=Double.valueOf(s1)+Double.valueOf(s2);
break;
case MINUS:
result=Double.valueOf(s1)-Double.valueOf(s2);
break;
case TIMES:
result=Double.valueOf(s1)*Double.valueOf(s2);
break;
case DIVISION:
result=Double.valueOf(s1)/Double.valueOf(s2);
break;
default:
result=null;
}
return result;
}
//方法:计算结果
public static Double doCalc(List list) {
Double d=0d;
if(list==null||list.isEmpty()) {
return null;
}
if(list.size()==1) {
System.out.println(list);
d=Double.valueOf(list.get(0));
return d;
}
ArrayList list1=new ArrayList<>();
for(int i=0;i