详解中缀表达式转化为后缀表达式并求值,附代码解释

本文介绍了如何将中缀表达式转换为后缀表达式并进行求值,详细阐述了转换和求值过程。在转换过程中,依据运算符优先级,遇到数字直接存入数组,遇到操作符与栈顶操作符比较并处理。代码中处理左括号采用递归,右括号则返回。在求值阶段,按照后缀表达式顺序遍历数组,数字入栈,操作符则从栈中取出两个元素进行计算并将结果压回栈,最终栈顶元素即为表达式值。
摘要由CSDN通过智能技术生成

思路

首先我们需要知道如何转化表达式并求值:首先不同的运算符有不同的优先级:对于(,),优先级最高,其次是*,/,最低是+,-。在从左往右扫描字符串时,遇到数字,就将其直接压入数组中。遇到操作符时,如果当前为空,那么直接压入中,如果不为空,那么将栈顶操作符优先级大于等于当前操作符的操作符pop出,并压入数组,直到栈顶操作符优先级小于当前操作符或为空才停止此次操作,并将当前操作符压入中。
由于在我的代码中遇到左括号是直接递归,右括号return,因此上面的处理中不需要考虑括号。
得到表达式后,我们就需要进行求值,首先我们得到的是一个数组,其中按后缀表达式中的顺序存储着操作符以及数字。那么我们从左往右遍历数组,当遇到数字时,将其压入栈中,遇到操作符时,在栈中提取出两个元素,并将两个元素根据操作符计算得到的值压入栈中,最后栈顶元素即为表达式的值。

代码

#include <iostream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

void showAndPush(vector<string> &expr, const string &s, char t = ' ') {
	expr.push_back(s);
	cout << s << t;
}

bool isOper(const string &s) { //数组中可能出现-2,+2等元素,因此size()==1为前提。
	return s.size() == 1 && (s[0] == '+' || s[0] == '-' || s[0] == '*' || s[0] == '/');
}

int cal(int num, int num1, char oper) {
	switch (oper) {
	case '+': return num + num1;
	case '-': return num - num1;
	case '*': return num * num1;
	case '/': return num / num1;
	}
}

//将输入的中缀表达式转化为后缀表达式
void infixToSuffix(int &p, const string &text, vector<string> &expr) {
	stack<char> stk;
	int len = text.length(), pre = expr.size();
	for (; p < len; ++p) {
		switch (text[p]) {
		case '+':
		case '-':
			while (!stk.empty()) {
				expr.emplace_back(1, stk.top());
				cout << stk.top(); stk.pop();
			}
			stk.push(text[p]);
			break;
		case '*':
		case '/':
			while (!stk.empty() && (stk.top() == '*' || stk.top() == '/')) {
				expr.emplace_back(1, stk.top());
				cout << stk.top(); stk.pop();
			}
			stk.push(text[p]);
			break;
		case '(':
			infixToSuffix(++p, text, expr); //遇到左括号就递归,将括号中的表达式当成一个独立的表达式,即可解决优先级的问题
			break;
		case ')':
			while (!stk.empty()) {
				showAndPush(expr, string(1, stk.top()));
				stk.pop();
			}
			return;
		case ' ': //遇到空格直接跳过不用处理
			break;
		default:
			string num;
			if (pre == expr.size() && !stk.empty()) { //这条if语句用于处理-2,(+2)等情况。这种情况下-+不算操作符。
				num.push_back(stk.top());
				stk.pop();
			}
			while (isdigit(text[p])) {
				num.push_back(text[p]);
				++p;
			}
			--p;
			showAndPush(expr, num);
		}
	}
	while (!stk.empty()) { //将栈中剩下的操作符全部压入数组中
		showAndPush(expr, string(1, stk.top()));
		stk.pop();
	}
}

int calculate(const vector<string> &expr) { //根据后缀表达式数组进行求值。
	stack<int> num;
	for (auto &iter : expr) {
		if (isOper(iter)) { //遇到操作符就将栈顶的两个元素出栈并求值,将结果再压入栈中,注意两个元素的顺序。
			int t = num.top(); num.pop();
			int t1 = num.top(); num.pop();
			num.push(cal(t1, t, iter[0]));
		} else {
			num.push(stoi(iter));
		}
	}
	return num.top(); //栈顶元素即为结果
}

void sln() {
	string text;
	getline(cin, text);
	vector<string> expr;
	int p = 0;
	infixToSuffix(p, text, expr); //将中缀表达式转化为后缀表达式
	cout << endl;
	cout << calculate(expr) << endl; //对后缀表达式求值
}

int main() {
	sln();
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值