java通过运用栈将中缀表达式转为后缀表达式并计算的实现

1.前言

中缀表达式和后缀表达式的概念在此不做赘述,只需记住中缀一般是人类习惯表达,即运算符在数中间,后缀是数在前,运算符在后即可

2.中缀转为后缀过程

  1. 遇到操作数。直接加入后缀表达式
  2. 遇到界限符。(入栈,遇到)则一次弹出栈内运算符并加入后缀表达式,直到弹出(为止
  3. 遇到运算符,依次弹出优先级等于或高于当前运算符的所有运算符,加入后缀表达式。若碰到(或栈空为止,再把当前运算符入栈

3.栈实现后缀表达式的计算流程

  1. 扫描后缀表达式
  2. 若操作数则压入栈,并继续扫描
  3. 若运算符则弹出栈顶两个元素,执行计算并将结果压入栈,执行
    注意后缀表达式在栈中先弹出的是右操作数

4.一道leetcode后缀习题

150.逆波兰表达式求值
在这里插入图片描述

class Solution {
    public int evalRPN(String[] tokens) {
        //用LinkedList实现存储数的栈
        LinkedList<Integer> stackNumber = new LinkedList();
        //如果是数字直接压入栈,否则弹出两个操作数进行计算
        for(int i=0;i<tokens.length;i++){
        	//判断是否为数
            if(!tokens[i].equals("+")&&!tokens[i].equals("-")&&!tokens[i].equals("*")&&!tokens[i].equals("/")){
                stackNumber.push(Integer.parseInt(tokens[i]));
            }else{
                int b = stackNumber.pop();//右操作数
                int a = stackNumber.pop();//左操作数
                int temp =getValue(a,b,tokens[i]);
                stackNumber.push(temp);
            }
        }
        return stackNumber.pop();


    }
    //计算
    public int getValue(int a,int b,String oper){
        if(oper.equals("+")){
            return a+b;
        }else if(oper.equals("-")){
            return a-b;
        }else if(oper.equals("*")){
            return a*b;
        }else if(oper.equals("/")){

            return a/b;

        }
        return 0;

    }

}

5.开始实现

设计一个计算器,可以加减乘除,并注意符号运算优先级
思路:
1.将中缀表达式改为后缀表达式
2.将后缀表达式用栈实现
注意:本题不涉及()[]{}等情况,只是单纯数字和加减乘除符号 且输入的int数字会被下截断为int

总代码放到后面。现在逐部分分析

1.获取中缀表达式

  • 通过控制台输入数据
  • 考虑到数据输入可能有空格,故使用nextLine()方法
  • 去除空格,使用replaceAll(" +“,”“),注意加号前面有空格,或者直接replaceAll(” “,”")(方法在nextLine()时不需要,了解即可)
  • 本实现只是简单加减乘除,所以需要逐个检查是否有意外字符
  • 对检查后的字符串进行分割
  • str.split(“(?<=。)|(?=。)”),每个分隔符单独作为一项(包括分隔符)
  • \\+|-|\\*|/表示分割±*/但是+和*需要转义
  • 如此便获得中缀表达式,即人输入的内容

2.中缀转后缀

过程在第二部分有说明:

  1. 遇到操作数。直接加入后缀表达式
  2. 遇到界限符。(入栈,遇到)则一次弹出栈内运算符并加入后缀表达式,直到弹出(为止
  3. 遇到运算符,依次弹出优先级等于或高于当前运算符的所有运算符,加入后缀表达式。若碰到(或栈空为止,再把当前运算符入栈

由于本题目简单,不需要考虑括号

3.处理优先级问题

操作符合有优先顺序,当前的运算符,入栈前要判断,栈必须依次弹出优先级等于或高于当前运算符的所有运算符,加入进入后缀表达式

4.代码和注释

import java.util.*;
/**
 * 设计一个计算器,可以加减乘除,并注意符号运算优先级
 * 思路:1.将中缀表达式改为后缀表达式
 *  	2.将后缀表达式用栈实现
 * 注意:本题不涉及()[]{}等情况,只是单纯数字和加减乘除符号 且输入的int数字会被下截断为int
 */
public class 计算器设计2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		//注意:如果使用next则会被空格中断,就是说空格后面的没取到,所以用nextLine()来获取以enter结尾
		String input = sc.nextLine().replaceAll(" +","");//以防万一输入有问题,先去除空格
		
		boolean ifOk = check(input);//检查输入是否只包括数字和+-*/
		if(!ifOk) {
			System.out.print("输入内容或者格式错误");
			return;
		}
		//对输入的表达式用正则分割,包括分隔符
		String[] exp = input.split("(?<=\\+|-|\\*|/)|(?=\\+|-|\\*|/)");
		//输入的数据操作符数组转为后缀表达式
		String[] out = infixExpression(exp);
		//后缀表达式获取值
		int value = evalRPN(out);
		System.out.println(value);

	}
	//将中缀表达式转换为后缀表达式
	public static String[] infixExpression(String[] exp) {
		String[] res = new String[exp.length];//创建符合后缀表达式的字符串数组
		String[] newInfixExp = new String[exp.length];
		LinkedList<String> stack = new LinkedList();//创建一个操作符的栈,用于存储和弹出操作符
		int index=0;//记录数组下标
		for(int i=0,j=0;i<exp.length;i++) {
			String temp = exp[i];
			if(!temp.equals("+")&&!temp.equals("-")&&!temp.equals("*")&&!temp.equals("/")){
				res[j]=temp;
				j++;
				index =j;
				
			}else {
				//根据优先级判断是否需要弹出运算符,时刻注意是否出现栈空情况
				while(!stack.isEmpty()&&priority(temp)<=priority(stack.peek())) {
					res[j]=stack.pop();
					j++;
					index =j;
				}
				stack.push(temp);
			}
		}
		//最后将栈中所有操作符放入表达式中
		while(!stack.isEmpty()) {
			res[index]=stack.pop();
			index++;
		}
		return res;
	}
	//对后缀表达式进行处理,tokens为以字符串为元素的后缀表达式各个操作数或操作符号:例如:tokens = ["2","1","+","3","*"]
	public static int evalRPN(String[] tokens) {
        LinkedList<Integer> stackNumber = new LinkedList();
        //如果是数字直接压入栈,否则弹出两个操作数进行计算
        for(int i=0;i<tokens.length;i++){
            if(!tokens[i].equals("+")&&!tokens[i].equals("-")&&!tokens[i].equals("*")&&!tokens[i].equals("/")){
                stackNumber.push(Integer.parseInt(tokens[i]));
            }else{
                int b = stackNumber.pop();//右操作数
                int a = stackNumber.pop();//左操作数
                int temp =getValue(a,b,tokens[i]);
                stackNumber.push(temp);
            }
        }
        return stackNumber.pop();


    }
    //计算
    public static int getValue(int a,int b,String oper){
        if(oper.equals("+")){
            return a+b;
        }else if(oper.equals("-")){
            return a-b;
        }else if(oper.equals("*")){
            return a*b;
        }else if(oper.equals("/")){

            return a/b;

        }
        return 0;

    }
    //检查输入
    public static boolean check(String input) {
    	char[] arr = input.toCharArray();
    	for(int i=0;i<arr.length;i++) {
    		if(!(arr[i]=='1'||arr[i]=='2'||arr[i]=='3'||arr[i]=='4'||arr[i]=='5'||arr[i]=='6'||arr[i]=='7'||arr[i]=='8'||arr[i]=='9'||arr[i]=='0'||arr[i]=='+'||arr[i]=='-'||arr[i]=='*'||arr[i]=='/')) {
    			return false;
    		}
    	}
    	
    	return true;
    	
    }
    //处理加减乘除的优先级问题
    public static int priority(String oper) {
        if (oper.equals("*") || oper.equals("/")) {
            return 1;
        }else {
            return 0;
        }
        
    }


}

运用截图:

在这里插入图片描述
综上,end;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值