一、题目描述:
输入一个中缀算术表达式,将其转换为后缀表达式。运算符包括+、-、*、/、(、)、=,参加运算的为小于10的自然数。(只考虑二元运算即可)
输入:
多组数据,每组数据一行,对应一个算术表达式,每个表达式均以“=”结尾。当表达式只有一个“=”时,输入结束。
输出
对于每组数据输出一行,为表达式的后缀式。
输入样例1:
9+(3-1)*3+1/2=
1+2=
=
输出样例1:
931-3*+12/+
12+
二、题目来源:
三、解题代码:
#include<iostream>
#include<stack>
#include<string>
#include<queue>
using namespace std;
int priority[128];//这个数组存+-*/等符号的ASCII码
int main() {
string str;
while (1) {
cin >> str;
if (str[0] == '=') {
break;
}
//定义优先级
priority['+'] = 1; priority['-'] = 1;
priority['*'] = 2; priority['/'] = 2;
priority['('] = 3; priority[')'] = 3;
priority['='] = 4;
queue<string>ans;//定义一个名为ans的queue容器来存储字符串,先进先出
stack<char>symbols;//定义一个名为symbols的栈来存储char类型的相关数据元素
int i = 0, start = 0;//start的作用是判断截取操作数的长度
int n = str.size();//获取输入字符串长度
while (i < n) {
while (i < n && priority[str[i]] == 0) {//判断是数字即操作数
i++;
}
if (start < i) {
ans.push(str.substr(start, i - start));//都是数字的情况,全部放入ans
}
if (priority[str[i]]) {//运算数
if (symbols.empty()) {//若为空,直接入栈
symbols.push(str[i]);
}
else {//不为空,判断
if (str[i] == ')') {
while (!symbols.empty() && symbols.top() != '(') {
string temp = "";//定义一个空的字符串
temp.push_back(symbols.top());//将symbols中弹出的元素放入temp中
ans.push(temp);//将temp添加到另一个容器ans中
symbols.pop();//从symbols中删除这个元素
}
symbols.pop();
}
else if (symbols.top() == '(' || priority[symbols.top()] < priority[str[i]]) {//如果为(,直接入栈,或优先级低的时候直接入栈
symbols.push(str[i]);
}
else {//如果栈顶元素更大,先出栈
while (!symbols.empty() && symbols.top() != '(' && priority[symbols.top()] >= priority[str[i]]) {//对现在栈内元素与新来元素优先级进行比较
string temp = "";//定义一个空的字符串
temp.push_back(symbols.top());//将symbols中弹出的元素放入temp中
ans.push(temp);//将temp添加到另一个容器ans中
symbols.pop();//从symbols中删除这个元素
}
symbols.push(str[i]);
}
}
}
i++;//符号操作完后,i下标后移
start = i;
}
while (!symbols.empty()) {//栈非空
string temp = "";//定义一个空的字符串
temp.push_back(symbols.top());//将symbols中弹出的元素放入temp中
ans.push(temp);//将temp添加到另一个容器ans中
symbols.pop();//从symbols中删除这个元素
}
while (ans.size() > 0) {
//if(ans.front()!="=") {
// cout << ans.front() << "";
// ans.pop();
//}
if (ans.front() != "=") {
cout << ans.front() << "";
}
else
{
}
ans.pop();
}
//cout << ans.front();
cout << endl;
}
return 0;
}
四、代码详解:
程序首先通过priority数组定义了各种运算符的优先级,然后使用queue和stack容器来分别存储操作数和运算符。
程序的核心逻辑部分是一个while循环,它会不断地从标准输入读取字符串。每次读取到一个字符串,程序会处理这个字符串,将其转换为一系列的操作数和运算符。然后,程序会根据运算符的优先级进行计算,并将结果输出到标准输出。
在处理字符串时,程序首先会跳过所有的非运算符字符,并将连续的操作数保存到ans队列中。当遇到运算符时,程序会根据当前运算符与栈顶运算符的优先级进行操作:
- 如果栈为空,或当前运算符的优先级大于栈顶运算符的优先级,则将当前运算符入栈。
- 如果当前运算符的优先级小于等于栈顶运算符的优先级,则将栈顶运算符出栈,并将其加入到ans队列中,直到遇到左括号或当前运算符的优先级大于栈顶运算符的优先级。然后将当前运算符入栈。
- 如果遇到右括号,则将栈内运算符依次出栈,并加入到ans队列中,直到遇到左括号为止。
在处理完一个字符串后,程序会将栈内剩余的运算符依次出栈,并加入到ans队列中。最后,程序会依次输出ans队列中的元素,并在输出=时结束。
这个程序支持基本的加减乘除和括号运算,可以处理比较复杂的数学表达式。
五、基本实现流程:
- 初始化: 首先定义了一个priority数组,用于存储运算符的优先级。然后定义了三个容器:queue<string> 用于存储操作数和最终结果;stack<char> 用于存储运算符;string 用于存储当前操作数。
- 读取输入: 使用无限循环,从标准输入读取字符串。程序会不断地处理输入,直到输入为 “=”。
- 处理字符串:
遍历字符串的每个字符。
如果遇到运算符,根据优先级进行处理:入栈、出栈、或直接入栈。
如果遇到操作数,将其添加到 ans 队列中。
如果遇到左括号,将其入栈。
如果遇到右括号,将其对应的左括号之前的运算符依次出栈,并加入到 ans 队列中,直到遇到左括号。
- 输出结果: 将 ans 队列中的元素依次输出,并在输出 “=” 时结束。