【北大计算概论A】【期末复习】专题:表达式

前缀、中缀、后缀表达式多次成为我们的作业题,值得专门开一个专题讲解一下。

一、后缀表达式

后缀表达式的计算是最经典的使用栈的题目,也是最适合计算机进行运算的表达式。

【题目分析】我们观察一下可以发现,我们每遇到一个运算符,就把存放数字的栈的前两个元素拿出来,用这个运算符运算后结果再放回数字的栈中,最终栈只剩下的一个元素就是答案。

#include <iostream>
#include <stack>
#include <cstring>
using namespace std;
stack<long long> s1;
string s;
int main() {
	while (true) {
	    bool cc = false;
		getline(cin, s);
		while (!s1.empty()) s1.pop();
		for (int i = 0; i < s.size() - 1; i++) {
			if (s[i] == ' ') continue;
			long long tmp = 0;
			bool flag = 0;
			while (s[i] >= '0' && s[i] <= '9') {
				flag = 1;
				tmp = (tmp << 3) + (tmp << 1) + s[i] - '0';
				i++;
			}
			if (flag) s1.push(tmp);
			else {
				long long a = s1.top(); s1.pop();
				long long b = s1.top(); s1.pop();
				if (s[i] == '+') s1.push(a + b);
				else if (s[i] == '-') s1.push(b - a);
				else if (s[i] == '*') s1.push(a * b);
				else if (s[i] == '/') {
				    if (a == 0) {
				        cout << "NaN" << endl;
				        cc = true;
				        break;
				    }
				    else s1.push(b / a);
				}
			}
		}
		if (cc) continue;
		cout << s1.top() << endl;
	}
	
	return 0;
}
二、中缀表达式

【2022计算概论A期末T8】四则运算表达式的值

【题目分析】中缀表达式对于计算机是较难处理的,这道题有三个难点:

①判断+和-是运算符还是正数、负数的含义

②运算符优先级的判断

③括号的处理

#include <iostream>
#include <stack>
#include <string>
#include <cctype>
#include <sstream>
using namespace std;

// 计算两个整数的操作
int calculate(int num1, char op, int num2) {
	switch (op) {
	case '+': return num1 + num2;
	case '-': return num1 - num2;
	case '*': return num1 * num2;
	case '/': return num1 / num2;
	}
	return 0;
}

// 获取操作符的优先级
int getPriority(char op) {
	if (op == '*' || op == '/') return 2;
	if (op == '+' || op == '-') return 1;
	return 0;
}

// 计算表达式的值
int evaluateExpression(const string& expression) {
	stack<int> nums;
	stack<char> ops;

	for (size_t i = 0; i < expression.length(); ++i) {
		char ch = expression[i];
		if (ch == '+' && (i == 0 || !isdigit(expression[i - 1])) && (expression[i - 1] != ')')) {
			int num = 0;
			i++;
			while (i < expression.length() && isdigit(expression[i])) {
				num = num * 10 + (expression[i++] - '0');
			}
			if (num) nums.push(num);
			--i;
		}
		else if (isdigit(ch) || (ch == '-' && (i == 0 || !isdigit(expression[i - 1])) && (expression[i - 1] != ')'))) {
			// 处理数字(包含负号开头的数字情况)
			int num = 0;
			bool negative = (ch == '-');
			if (negative && expression[i + 1] == '(') {
				ops.push('*');
				nums.push(-1);
				continue;
			}
			if (negative) ++i;
			while (i < expression.length() && isdigit(expression[i])) {
				num = num * 10 + (expression[i++] - '0');
			}
			if (negative) num = -num;
			nums.push(num);
			--i;
		}
		else if (ch == '(') {
			ops.push(ch);
		}
		else if (ch == ')') {
			while (!ops.empty() && ops.top() != '(') {
				int num2 = nums.top(); nums.pop();
				int num1 = nums.top(); nums.pop();
				char op = ops.top(); ops.pop();
				nums.push(calculate(num1, op, num2));
			}
			if (!ops.empty()) ops.pop();  // 弹出 '('
		}
		else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
			while (!ops.empty() && getPriority(ops.top()) >= getPriority(ch)) {
				int num2 = nums.top(); nums.pop();
				int num1 = nums.top(); nums.pop();
				char op = ops.top(); ops.pop();
				nums.push(calculate(num1, op, num2));
			}
			ops.push(ch);
		}
	}

	while (!ops.empty()) {
		int num2 = nums.top(); nums.pop();
		int num1 = nums.top(); nums.pop();
		char op = ops.top(); ops.pop();
		nums.push(calculate(num1, op, num2));
	}

	return nums.top();
}
int main() {
	string expression;
	while (getline(cin, expression)) {
		cout << evaluateExpression(expression) << endl;
	}
	return 0;
}
三、前缀表达式

题目分析:前缀表达式可以通过函数的递归调用实现。

#include <iostream>
#include <stdlib.h>
#include <cstring>
using namespace std;
string s;
int i = 0;
double calc() {
	while (s[i] == ' ') i++;
	if (s[i] == '+') {
		i++;
		double a = calc();
		double b = calc();
		return a + b;
	} else if (s[i] == '-') {
		i++;
		double a = calc();
		double b = calc();
		return a - b;
	} else if (s[i] == '*') {
		i++;
		double a = calc();
		double b = calc();
		return a * b;
	} else if (s[i] == '/') {
		i++;
		double a = calc();
		double b = calc();
		return a / b; 
	} else {
		int start = i;
		while ((s[i] >= '0' && s[i] <= '9') || s[i] == '.') i++;
		string str = s.substr(start, i - 1);
		char temp[str.size()] = {0};
		for (int i = 0; i < str.size(); i++) temp[i] = str[i];
		return atof(temp);
	}
}
int main() {
	getline(cin, s);
	printf("%f\n", calc());
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值