中缀表达式求值(Java)

中缀表达式求值(Java)

通常使用的是中缀表达式,例如:2+(3-1)*2;计算中缀表达式一般先转换成后缀表达式,后计算;

中缀表达式

中缀表达式是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:3 + 4)

  • 中缀表达式的求解需要两个栈来存储,且设置为泛型,一个栈存操作数,一个栈存操作符,需要输入一个表达式字符串并将其转为字符串数组以提取有效字符。
后缀表达式
  • 后缀表达式求解: 从左到右扫描后缀表达式,若遇操作数,则进栈;若遇运算符,则从栈中退出两个元素,先退出的放到运算符的右边,后退出的 放到运算符左边,运算后的结果再进栈,直到后缀表达式扫描完毕。此时,栈中仅有一个元素,即为运算的结果。
中缀表达式转后缀表达式思路
1.定义两个栈,一个stack栈结构存储操作符,一个List结构存储后缀表达式结果

2.首先读取到数字,直接存入list中

3.当读取到左括号"("时,直接压栈,当读取到运算符时,分以下两种情况讨论
 1.当运算符栈为空或者栈顶操作符的优先级小于当前运算符优先级时(如+和-的优先级低于 * 和 /),直接入栈  
 2.当运算符不为空时且栈顶操作符的优先级大于或等于当前运算符优先级时,循环执行出栈操作并加入list中,直到遇到优先级小于当前运算符的元素为止。循环执行完后再将当前运算符压栈。另外需要注意的是,只有遇到右括号时,左括号才出栈
4.当遇到右括号")"时,循环执行出栈操作并加入到list中,直到遇到左括号为止。并将左括号弹出,但不加入list中
5.表达式的值读取完后,将操作符栈中的所有元素弹出并加入到list中
代码如下

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;

public class Calculator {
	public  static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		String expression = sc.nextLine();
		List<String> infixexpression = Depositlist(expression);//中缀表达式
		System.out.println("中缀表达式为:"+ infixexpression );
		List<String> calculateexpression = parsexpreesion(infixexpression);//后缀表达式
		System.out.println("后缀表达式为:"+calculateexpression);
		System.out.printf("Answer=%d", calculate(calculateexpression)); //计算结果
	}

	
	public static List<String> parsexpreesion(List<String> list) {//方法:将得到的中缀表达式对应的转换后缀表达式对应的List
		//定义两个栈
		Stack<String> s1 = new Stack<String>(); // 符号栈
		List<String> s2 = new ArrayList<String>(); // 储存中间结果的Lists2
		
		
		for(String item: list ) {
			if(item.matches("\\d+")) {//如果是一个数加入s2
				s2.add(item);
			} else if (item.equals("(")) {
				s1.push(item);
			} else if (item.equals(")")) {
				
				while(!s1.peek().equals("(")) {//如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
					s2.add(s1.pop());
				}
				s1.pop();//将 ( 弹出 s1栈, 消除小括号
			} else {
				while(s1.size() != 0 && operation.getValue(s1.peek()) >= operation.getValue(item) ) {
					s2.add(s1.pop());
				}
				
				s1.push(item);
			}
		}
		
	
		while(s1.size() != 0) {	//将s1中剩余的运算符依次弹出并加入s2
			s2.add(s1.pop());
		}

		return s2; 
		
	}
	
	public static List<String> Depositlist(String s) {
		
		List<String> list = new ArrayList<String>();//定义一个List,存放中缀表达式 对应的内容
		int i = 0; 
		String str; 
		char c; 
		do {
			
			if((c=s.charAt(i)) < 48 ||  (c=s.charAt(i)) > 57) {
				list.add("" + c);
				i++; 
			} else { 
				str = ""; //先将str 置成"" '0'[48]->'9'[57]
				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;
	}
	
	//将一个逆波兰表达式, 依次将数据和运算符 放入到 ArrayList中
	public static List<String> getListString(String suffixexpression) {	
		String[] split = suffixexpression.split(" ");//将 suffixexpression 分割
		List<String> list = new ArrayList<String>();
		for(String ele: split) {
			list.add(ele);
		}
		return list;
		
	}
	public static int calculate(List<String> list) {
		Stack<String> stack = new Stack<String>();// 创建栈
		for (String item : list) {
			if (item.matches("\\d+")) { //使用正则表达式匹配多位数
				stack.push(item);
			} else {
				int num2 = Integer.parseInt(stack.pop());	// 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);
			}
			
		}
		
		return Integer.parseInt(stack.pop());
	}

}
//编写一个类 Operation 可以返回一个运算符 对应的优先级
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;
		default:
			
			break;
		}
		return result;
	}
	
}


运行结果
1+2*(6-3)-6/2
中缀表达式为:[1, +, 2, *, (, 6, -, 3, ), -, 6, /, 2]
后缀表达式为:[1, 2, 6, 3, -, *, +, 6, 2, /, -]
Answer=4
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值