1-3 表达式转换 (25 分)
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。
输入格式:
输入在一行中给出不含空格的中缀表达式,可包含+
、-
、*
、\
以及左右括号()
,表达式不超过20个字符。
输出格式:
在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。
输入样例:
2+3*(7-4)+8/4
结尾无空行
输出样例:
2 3 7 4 - * + 8 4 / +
结尾无空行
-
从左到右扫描每一个字符。如果扫描到的字符是操作数(如a、b等),就直接输出这些操作数。
-
如果扫描到的字符是一个操作符,分三种情况:
(1)如果堆栈是空的,直接将操作符存储到堆栈中(push it)
(2)如果该操作符的优先级大于堆栈出口的操作符,就直接将操作符存储到堆栈中(push it)
(3)如果该操作符的优先级低于堆栈出口的操作符,就将堆栈出口的操作符导出(pop it), 直到该操作符的优先级大于堆栈顶端的操作符。将扫描到的操作符导入到堆栈中(push)。
-
如果遇到的操作符是左括号"(”,就直接将该操作符输出到堆栈当中。该操作符只有在遇到右括号“)”的时候移除。这是一个特殊符号该特殊处理。
-
如果扫描到的操作符是右括号“)”,将堆栈中的操作符导出(pop)到output中输出,直到遇见左括号“(”。将堆栈中的左括号移出堆栈(pop )。继续扫描下一个字符
-
如果输入的中缀表达式已经扫描完了,但是堆栈中仍然存在操作符的时候,我们应该讲堆栈中的操作符导出并输入到output 当中。
代码:
注:这道题的难点主要是在处理数字前的正负号上,同时还应该注意数字有小数点并且不是一位数字。
#include <bits/stdc++.h>
using namespace std;
stack<char> st;
map<char, int> mp;
int main()
{
mp['+'] = mp['-'] = 1; //定义运算符的优先级
mp['*'] = mp['/'] = 2;
string s = "";
cin >> s;
int flag = 1;
for (int i = 0; i < s.length(); ++i)
{
if (isdigit(s[i]) || ((!i || s[i - 1] == '(') && (s[i] == '+' || s[i] == '-')))
{ //处理操作数
if (!flag)
cout << " ";
else
flag = 0;
if (s[i] != '+')
cout << s[i];
while (s[i + 1] == '.' || isdigit(s[i + 1]))
cout << s[++i]; //小数继续往后读
}
else
{ //处理运算符
if (s[i] == '(')
st.push(s[i]); //(:压栈
else if (s[i] == ')')
{ //):将栈顶的运算符弹出并输出,直到遇到左括号(出栈,不输出)
while (!st.empty() && st.top() != '(')
{
cout << " " << st.top();
st.pop();
}
st.pop();
}
else if (st.empty() || mp[s[i]] > mp[st.top()])
st.push(s[i]); //s[i]的优先级比栈顶元素的大
else
{
while (!st.empty() && st.top() != '(' && mp[s[i]] <= mp[st.top()])
{ //s[i]的优先级比栈顶元素的小或等
cout << " " << st.top();
st.pop();
}
st.push(s[i]);
}
}
}
while (!st.empty())
{
cout << " " << st.top();
st.pop();
}
return 0;
}