详细理解中缀表达式并实现

Posted 勇敢牛牛不怕困难@帅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详细理解中缀表达式并实现相关的知识,希望对你有一定的参考价值。

中缀表达式的实现及概念

在这里插入图片描述
每日一笑:
公交车上,一丑女不小心踩了一个男人脚。男人大怒:你再踩一下试试,我让你好看!丑女大喜,急忙又踩了一脚道:太好了大哥,这下不用花钱整容了。

中缀表达式的定义

中缀表达式是一个通用的算术或逻辑公式表示方法。
在这里插入图片描述
中缀表达式就是我们通常所理解的数学公式或者是表达式例如:1+2/(1+1)+9*2类似这样简单的加减乘除运算的例子,我们称之为中缀表达式。
形如下图:
在这里插入图片描述
以人们的理解思路,便是以中缀形式去走的,更便于理解。但是计算机呢,大多数不是以中缀的方式去存与计算的,对于计算机来讲中缀表达式不便于理解。

中缀表达式的分解过程

例子:
在这里插入图片描述
首先我们需要两个容器来分别存放数字类型和字符类型,在这里可以选择栈这一容器,栈是先进后出,后进先出的方式,刚好满足后到先处理,根据优先级判断。

第一步: 一个符号栈operatorStack,一个数字栈numberStack,刚开始栈都为空。

在这里插入图片描述
第二步: 识别表达式第一个字符的类型,是符号就入符号栈,如果是数值行就入数字栈,显然左括号是符号,就入符号栈;
在这里插入图片描述
第三步: 接着循环下一位,判断出10为数值所以入数字栈。在这里插入图片描述
第四步: +号为字符,入字符栈
在这里插入图片描述
第五步: 20为数字,入数字栈
在这里插入图片描述
第六步: /为字符,入字符栈
在这里插入图片描述
第七步: 2为数字,入数字栈

在这里插入图片描述
第八步: *为字符,入字符栈
但是,由于符号栈的栈顶元素为/,优先级和 ✖乘法的优先级相等,但是➗在✖乘号之前 所以要先进行运算,运算之后在入栈。数字栈弹两元素先弹出的作为除数,后弹出的作为被除数。运算结果存入数字栈中。

在这里插入图片描述
最后乘号入符号栈
在这里插入图片描述

第九步: 3为数字,入数字栈
在这里插入图片描述
**第十步:**此时判断为右括号,就说明要将离右括号最近的左括号里面的数字要进行运算,运算结束之后 左括号弹栈,运算结果入栈。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第十一步: /为符号,入符号栈
在这里插入图片描述
第十二步: 2为数字入数字栈
在这里插入图片描述
第十三步: 除法的优先级高于加法,所以优先处理除法运算。
在这里插入图片描述
加法入符号栈
在这里插入图片描述
第十四步: 8为数字 进入数字栈,由于8为最后一个元素,所以要进行运算,将运算结果放入到数字栈中,此时的符号栈为空。
在这里插入图片描述
到这里中缀表达式的整个分解过程就结束了!,最后表达式的结果便是保存在数字栈中

接下来代码实现

package expression;

import java.util.Stack;

public class InfixExpression {//中缀表达式

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		String  expression = "(10+20/2*3)/2+8";
		int result = evaluteExpression(expression);
		System.out.println(result);
	}
	public static int evaluteExpression(String evaluteExpression) {
		Stack<Integer> numberStack = new Stack<>();//定义数字栈
		Stack<Character> operatorStack = new Stack<>();//定义符号栈
		evaluteExpression = formatExpression(evaluteExpression);//格式化
		String[] tokens = evaluteExpression.split(" ");//分割字符串为字符数组
		for(String token:tokens) {//遍历
			if(token.length()==0) {//如果字符数组为空直接跳过
				continue;
			}else if(token.charAt(0)=='(') {//为左括号直接入栈
				operatorStack.push('(');
			}else if(token.charAt(0)=='+'||token.charAt(0)=='-') {//为+或为-号时,都要处理符号栈里的元素
				while(!operatorStack.isEmpty()&&(operatorStack.peek()=='+'||operatorStack.peek()=='-'||
				operatorStack.peek()=='*'||operatorStack.peek()=='/')) {
					processAnOperator(operatorStack,numberStack);
				}
				operatorStack.push(token.charAt(0));
			}else if(token.charAt(0)=='*'||token.charAt(0)=='/') {//为*或为/号时,都要处理符号栈里*,/元素
				while(!operatorStack.isEmpty()&&(operatorStack.peek()=='*'||operatorStack.peek()=='/')) {
					processAnOperator(operatorStack,numberStack);
				}
				operatorStack.push(token.charAt(0));
			}else if(token.charAt(0)==')') {//为右括号时处理整个括号里的元素值
				while(operatorStack.peek()!='(') {
					processAnOperator(operatorStack,numberStack);
				}
				operatorStack.pop();
			}else {//为数值类型
				numberStack.push(new Integer(token));
			}	
		}
		while(!operatorStack.isEmpty()) {//直到符号栈不为空 一直处理
			processAnOperator(operatorStack,numberStack);
		}
		return numberStack.pop();
	}
	
	
	
	public static void processAnOperator(Stack<Character> operatorStack,Stack<Integer> numberStack) {//运算处理
		char ch = operatorStack.pop();
		int num1 = numberStack.pop();
		int num2 = numberStack.pop();
		switch(ch) {
		case '+':numberStack.push(num2+num1);break;
		case '-':numberStack.push(num2-num1);break;
		case '/':numberStack.push(num2/num1);break;
		case '*':numberStack.push(num2*num1);break;
		}
	}
	
	
	
	
	public static String formatExpression(String evaluteExpression ) {//格式化
		StringBuilder sb = new StringBuilder();
		for(int i=0;i<evaluteExpression.length();i++) {
			char c = evaluteExpression.charAt(i);
			if(c=='+'||c=='-'||
			c=='*'||c=='/'||
			 c=='('||c==')') {
				sb.append(' ');
				sb.append(c);
				sb.append(' ');
			}else {
				sb.append(c);
			}
			
		}
		
		return sb.toString();
	}

}

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

总结

对于中缀表达式,我们要明确两个观点 一个是需要两个栈来存储数字型元素和符号型元素,遇到符号时判断符号栈是否为空,为空直接入栈,不为空的前提下在判断运算符的优先级,在做处理。最后运算的结果保存在数字栈中,只需弹栈即可!

以上是关于详细理解中缀表达式并实现的主要内容,如果未能解决你的问题,请参考以下文章

表达式的计算(中缀表达式转为后缀表达式或逐步计算)

中缀表达式转后缀表达式--C# 代码实现

中缀表达式检测并转换后缀表达式,计算后缀表达式的结果

将中缀表达式转换成后缀表达式

波兰表达式与逆波兰表达式介绍及中缀表达式转逆波兰表达式代码实现

计算中缀表达式的方法