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

中缀表达式的实现及概念

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

中缀表达式的定义

中缀表达式是一个通用的算术或逻辑公式表示方法。
在这里插入图片描述
中缀表达式就是我们通常所理解的数学公式或者是表达式例如: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语言实现中缀表达式转后缀表达式的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_SIZE 100 // 定义结构 typedef struct { char data[MAX_SIZE]; int top; } Stack; // 初始化 void initStack(Stack *s) { s->top = -1; } // 判断是否为空 int isStackEmpty(Stack *s) { return s->top == -1; } // 判断是否已满 int isStackFull(Stack *s) { return s->top == MAX_SIZE - 1; } // 入 void push(Stack *s, char value) { if (isStackFull(s)) { printf("Stack is full.\n"); return; } s->data[++(s->top)] = value; } // 出 char pop(Stack *s) { if (isStackEmpty(s)) { printf("Stack is empty.\n"); return '\0'; } return s->data[(s->top)--]; } // 获取顶元素 char peek(Stack *s) { if (isStackEmpty(s)) { printf("Stack is empty.\n"); return '\0'; } return s->data[s->top]; } // 判断运算符的优先级 int getPriority(char operator) { switch (operator) { case '+': case '-': return 1; case '*': case '/': return 2; case '^': return 3; default: return 0; } } // 中缀表达式转后缀表达式 void infixToPostfix(char *infix, char *postfix) { Stack operatorStack; initStack(&operatorStack); int i, j; char ch, topOperator; for (i = 0, j = 0; infix[i] != '\0'; i++) { ch = infix[i]; if (ch >= 'a' && ch <= 'z') { // 如果是操作数,直接输出到后缀表达式中 postfix[j++] = ch; } else if (ch == '(') { // 如果是左括号,入 push(&operatorStack, ch); } else if (ch == ')') { // 如果是右括号,将中的运算符弹出并输出,直到遇到左括号 while ((topOperator = pop(&operatorStack)) != '(') { postfix[j++] = topOperator; } } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '^') { // 如果是运算符 // 将优先级比当前运算符高或者相等的运算符弹出并输出 while (!isStackEmpty(&operatorStack) && peek(&operatorStack) != '(' && getPriority(ch) <= getPriority(peek(&operatorStack))) { postfix[j++] = pop(&operatorStack); } push(&operatorStack, ch); // 将当前运算符入 } } // 将中剩余的运算符弹出并输出 while (!isStackEmpty(&operatorStack)) { postfix[j++] = pop(&operatorStack); } postfix[j] = '\0'; // 结尾加上字符串结束符 } int main() { char infix[MAX_SIZE]; char postfix[MAX_SIZE]; printf("Enter an infix expression: "); fgets(infix, sizeof(infix), stdin); infix[strlen(infix) - 1] = '\0'; // 去掉末尾的换行符 infixToPostfix(infix, postfix); printf("Postfix expression: %s\n", postfix); return 0; } ``` 这个示例代码实现了一个简单的中缀表达式转后缀表达式的程序。运行代码后,用户需要输入一个中缀表达式,程序会将其转换为后缀表达式并输出。 注意,在这个示例中,假设输入的中缀表达式合法且只包含小写字母、运算符和括号。如果输入的中缀表达式有语法错误或不符合规范,程序可能会产生错误的输出。在实际的应用中,可能需要对输入进行更严格的验证和错误处理。 希望这个示例能帮助你理解如何使用C语言实现中缀表达式转后缀表达式!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牛牛最爱喝兽奶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值