蓝桥杯 表达式计算(java)

本文详细解析了如何使用栈解决中缀表达式的计算问题,包括操作数栈和操作符栈的设计,以及处理括号和不同优先级运算符的策略。通过具体示例,阐述了算法的实现步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我。。。好久没有来写博客了,不是因为我没有刷题了,而是我卡在了算法训练的前几道题上,什么AC自动树,压缩状态dp,都要把我弄疯了,我以为后面的题的难度是递增的,搞得我都怀疑人生了,在被大佬嘲笑之后,我才发现后面的题要简单多了,于是先做几道题重拾信心,今天就是表达式计算

题目描述:
输入一个只包含加减乖除和括号的合法表达式,求表达式的值。其中除表示整除。(也就是给你一个中缀表达式求出它的值)

**题目分析:**这道题很短,给人一种几分钟就可以搞定的感觉,但是小小身体蕴含大大能量。这道题我的思路是, 首先给定的是一个中缀表达式,那么我们的任务就是求出这个中缀表达式的值,因为之前做过这种题,一下就想到了栈,定义两个栈,一个用来存放操作数(Integer),一个用来存放操作符(Character),
规则:

  1. 首先我们在操作符栈先放一个字符‘#’,(为什么要放这个操作符呢?是为了防止出现空栈的情况,那这里我就要反问你了,既然你为了防止出现空栈,你为什么不将操作数栈中也先放一个数,这里我要说明的是,在我们读取输入的表达式时,我们的计算都是根据操作符来进行的,后面你就会知道了)
  2. 然后我们读取输入的表达式,我们用一个字符串来存放,然后用charAt()来分别获取每一个字符,但是这里需要注意的是如果我们的操作数是两位或者两位以上,那这里就需要有特殊处理,如果当前读入的是数字我们就继续往下读直到读到操作符为止,记录当前的下标和之前的下标,对字符串进行截取,然后转化为int类型,
  3. 然后对我们读入的数据进行判断,如果是操作数,我们就直接进栈,如果是操作符,取出操作符的栈顶元素,判断栈顶元素和读入操作符的优先级(’ # '的优先级为0, ’ + ’ ’ - '的优先级为1, '* ’ ’ / '的优先级为2 ’ ( '的优先级为3 ),如果读入的操作符的优先级更高,我们就让他直接进栈,否则,我们就让操作数栈出栈两个数,操作符栈出栈栈顶元素,然后进行运算,在将运算结果放到操作数栈,然后继续判断当前操作符和操作符栈的栈顶元素的优先级(这里我会单独写成一个方法 opration() )。
  4. 如果中缀表达式中没有括号,那么我们的任务就完成了,但是表达式中式会出现括号的,所以我们还要继续考虑,当我们读入到‘( ’我们直接像之前的操作一样让他入栈,然后继续读入,如果是数字就进操作数栈,因为我将‘( ‘的优先级是设置的最高的,如果按照之前的方法就是错误的,所以当读入操作符的时候我们增加一个选项,是否栈顶元素是’( ’ 如果是的话 ,就将该操作符入栈,后面的操作和之前一样了(执行3),直到读到了’ ’ )’ 我们就进行 opration(),直到遇到了’ ( '将其出栈,
  5. 执行3。当读入完毕了之后,我们判断操作符栈是否读到了结尾,也就是栈顶元素是否是’#‘,然后对栈进行操作。直到操作符栈的栈顶为’#‘。
  6. 输出操作数的栈顶元素

我在写代码时没有考虑到的问题:

  1. 我在处理当读入括号的时候,一直不知道放到哪里处理,结果经过了反复而又痛苦的尝试后,我才知道将其放到run函数中
  2. 没有考虑到操作数不仅仅只有一位的情况
  3. 当操作符的优先级小于栈顶元素的优先级,没有考虑到重复操作,以及读到’(‘的情况。

献上代码:


package algothm_training;

import java.util.Scanner;
import java.util.Stack;

//表达式计算  我竟然忘了 怎样将一个类放到数组中来
public class Main_expresioncalulate03 {
	static Stack<Integer> number=new Stack<Integer>();   //操作数栈
	static Stack<Character> oprate=new Stack<Character>();   //操作符栈
	static String expresion;   
	static int i=0;

	public static void main(String[] args) { //2*(3+5)+7/1-4
		Scanner scanner =new Scanner(System.in);
	    expresion=scanner.nextLine();
	    oprate.push('#');    //先将操作符栈中放入#  好进行之后的优先级比较
	    while(i<expresion.length()) {	
	    	char temp=expresion.charAt(i);
	    		run(temp);     
	    		i++;
	    }
	    while(oprate.peek()!='#') {    //如果操作符栈的栈顶元素不是#
   	    	opration();         
	    }
	    System.out.println(number.peek());   //输出操作数栈的栈顶元素
	}
	
	
	static void run(char temp) {  
		if(temp>=48&&temp<=57) {
			int k=i+1;
    		while(k<expresion.length()&&expresion.charAt(k)>=48&&expresion.charAt(k)<=57) {  //如果l还是数字
    			k++;
    		}
    		int num=Integer.parseInt(expresion.substring(i,k));
    		i=k-1;
    		number.push(num);
    	}else {
    		char top=oprate.peek();
    		int top_first=first(top);   //栈顶元素的优先级
    		int temp_first=first(temp);  //当前要插入的元素的优先级    		
    		if(temp_first>top_first||top=='(') {
    			oprate.push(temp);
    		}else if(temp==')') {
    			while(temp!='(') {
    				opration();
    				temp=oprate.peek();
    			}
    			oprate.pop();
    		}else{
				while(temp_first<=top_first&&top!='(') {//哦哦这里是有问题的!!!!!!!!!!
					opration();
					top=oprate.peek();  //再次取出栈顶元素  看栈顶元素和当前元素的优先级
					top_first=first(top);
				}
				oprate.push(temp);
			}
    	}
		
	}
	//出栈计算
	static void opration(){
		char oprate0=oprate.pop();
		int num1=number.pop();
		int num2=number.pop();                  
		int num3;
		switch(oprate0) {
		case '+':
			num3=num2+num1;
			break;
		case '-':
			num3=num2-num1;
			break;
		case '*':
			num3=num2*num1;
			break;
		case '/':
			num3=num2/num1;
			break;
		default:
			num3=0;
			break;
		}
		number.push(num3);		
	}
	//返回符号优先级
	static int first(char operate) {//478*7*2-82348/2+(83*23-6466)
		int fir=0;
		switch(operate) {
		case '#':
			fir=0;
			break;
		case '+': 
		case '-':
			fir=1;
			break;
		case '*':
		case '/':
			fir=2;
			break;
		case '(':
			fir=3;
		default:
			break;
		}
		return fir;
	}
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值