逆波兰表达式的求解(Java)思路分析及源代码

import java.util.ArrayList;
import java.util.Scanner;
import java.util.Stack;
/*

  • 中缀转后缀:
  • 1.初始化俩个栈:运算符栈s1和存储中间结果的栈s2;
  • 2.从左到右扫描中缀表达式
  • 3.如果遇到操作数的时候,直接压入栈s2
  • 4.如果遇到操作符的时候,比较其与s1栈顶运算符的优先级:
  • (1).如果s1为空或者栈顶运算为左括号“(”,则直接让此运算符入栈;
  • (2)否则。若优先级比栈顶运算符高,也将运算符压入栈s1
  • (3)否则,将s1栈顶运算符弹出压入到s2中,再次转入到4.1与栈顶操作符进行比较
  • 5.遇到括号时:
  • (1)如果遇到左括号就直接压入s1,
  • (2)如果遇到右括号,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,然后将这一对
  • 括号丢弃
  • 6.重复步骤2至5,直到表达式的最右边
  • 7,将s1中剩余运算符依次弹出并压入s2
  • 8.依次弹出s2中表达式,并逆序输出的结果就为后缀表达式
    */

public class Main {
public static void main(String[] args) {
/*
* 所谓前缀。中缀,后缀是相对于操作符来说的,前缀是说操作符在前面
*/
Scanner sc=new Scanner(System.in);
String s=sc.nextLine();
InversePolishExpression ipe=new InversePolishExpression();//逆波兰表达式的计算
ArrayList infixList=ipe.InfixExpression(s);//将字符串转换成中缀表达式
System.out.println(“中缀表达式为:”+infixList);
ArrayList suffixList=ipe.infixSuffix(infixList);//将中缀表达式转换成后缀表达式
System.out.println(“后缀表达式为:”+suffixList);
int result=ipe.CalculateTheSuffix(suffixList);//计算后缀表达式
System.out.println(result);
}
}

class InversePolishExpression{//逆波兰表达式的计算
/*
* //将字符串转换成中缀表达式
/
public ArrayList InfixExpression(String s){
ArrayList infixList=new ArrayList();//用来存放中缀表达式的集合
/

* 如果直接采用这个遍历字符串的方式,将数字和操作符取出,会出现一些问题
* 例如:27+8 就会变成 2 7 + 8 在计算的过程中出现一些问题。
*
for(int i=0;i<s.length();i++) {//遍历字符串
String temp=String.valueOf(s.charAt(i));//将每一个字符转换成字符串,存入前缀集合中
infixList.add(temp);
}
*/

	int i=0;//遍历字符串的索引
	do {
		String str="";//拼接多位数字的字符串
		if(s.charAt(i)<48||s.charAt(i)>57) {//如果是操作符的话,就直接入集合
			infixList.add(String.valueOf(s.charAt(i)));
			i++;
		}else {//如果是数字的话,就要考虑多位数的情况
			while(i<s.length()&&s.charAt(i)>=48&&s.charAt(i)<=57) {
				str+=s.charAt(i);
				i++;
			}
			infixList.add(str);
			str="";
		}
	}while(i<s.length());
	return infixList;
}
/*
 * //将中缀表达式转换为后缀表达式
 */
public ArrayList<String> infixSuffix(ArrayList<String> infixList){
	Stack<String> s1=new Stack<String>();//用来存放操作符的栈
	/*
	 * 这里由于栈s2没有出栈的情况,而且最后转换为后缀表达式的时候,还需要逆序输出
	 * 因此,为了简化过程,将中间存储情况直接add进后缀的集合中
	 */
	//Stack<String> s2=new Stack<String>();//用来存放中间结果的栈
	ArrayList<String> suffixList=new ArrayList<String>();//用来存放后缀表达式的集合
	for(String s:infixList) {//遍历前缀集合
		if(s.matches("\\d+")) {//如果是数字就直接加到后缀表达式中
			suffixList.add(s);
		}else if(s.equals("(")){//如果是左括号也直接加到后缀表达式中
			s1.push(s);
		}else if(s.equals(")")) {//如果遇到有括号,就要不断的将栈中操作符弹出,直到遇到(括号结束,然后将一对括号消除
			while(!s1.peek().equals("(")) {
				suffixList.add(s1.pop());
			}
			s1.pop();
		}else {//如果是操作符,就要判断该操作符与栈顶的操作符的优先级
			while(s1.size()>0&&Opertion.getValue(s1.peek())>=Opertion.getValue(s)) {
				suffixList.add(s1.pop());
			}
			s1.push(s);
		}
	}
	while(s1.size()>0) {//遍历结束以后,将栈中剩余的操作符全部压到后缀表达式中
		suffixList.add(s1.pop());
	}
	return suffixList;
}

/*
 * 计算后缀表达式的结果
 */
public int CalculateTheSuffix(ArrayList<String> suffixList) {
	Stack<String> stack=new Stack<String>();
	for(String s:suffixList) {//遍历后缀表达式
		if(isOpertion(s)) {//如果是操作符,就取出栈顶和次栈顶俩个数进行计算
			int num1=Integer.valueOf(stack.pop());
			int num2=Integer.valueOf(stack.pop());
			int result=count(num1, num2, s);
			stack.push(String.valueOf(result));
		}else {
			stack.push(s);
		}
	}
	return Integer.valueOf(stack.pop());
}

/*
 * 判断字符串是否为操作符
 */
public boolean isOpertion(String s) {
	return s.equals("+")||s.equals("-")||s.equals("*")||s.equals("/");
}
/*
 * 计算值
 */
public int count(int num1,int num2,String opertion) {
	switch (opertion) {
	case "+":
		return num1+num2;
	case "-":
		return num2-num1;
	case "*":
		return num1*num2;
	case "/":
		return num2/num1;

	default:
		throw new RuntimeException("操作符错误");
	}
}

}

class Opertion{//判断操作符的优先级
private static int ADD=1;//加的优先级为1
private static int SUB=1;//减的优先级为1
private static int MUL=2;//乘的优先级为2
private static int DIV=2;//除的优先级为2

public static int getValue(String opertion) {
	int result=0;
	switch (opertion) {
	case "+":
		result=ADD;
		break;
	case "-":
		result=SUB;
		break;
	case "*":
		result=MUL;
		break;
	case "/":
		result=DIV;
		break;
	default:
		System.out.println("不存在"+opertion+"运算符");
	}
	return result;
}

}

结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值