题源:
PTA 数据结构2 习题3.11 表达式转换
题面没有讲的细节:
1.题面中出现‘\’来描述除号 但实际上是‘/’ 不会出现‘\’
2.操作数不一定是整数 可能会出现多位数 小数 负数 前面可能会出现无意义的正号来表示正负
12,12.3,-12,+12都是可能出现的操作数
3.无意义的正号在输出时需要忽略掉 即使输入时有
输入的 +12 输出时应只为 12
注意:
1.1 2和12是否区分
2.前文提及的细节是否处理
算法:
后缀表达式运算:
从左到右
遇到数字 直接入栈
遇到操作符 弹出两个数字 按照操作符运算得到结果 将结果入栈
中缀转后缀算法1:
从左到右遍历中缀表达式
遇到数字 直接输出
遇到操作符
若为‘(’ 直接入栈
若为‘ )’不断弹出元素并输出 直到弹出‘(’ 注意!括号都不用输出!
若栈空 或 栈顶元素为括号 直接入栈
若操作符优先级大于栈顶元素优先级 直接入栈
否则 不断弹出栈顶元素并输出 直到栈顶元素为括号 或 栈空 或 操作符优先级大于栈顶元素优先级
之后再入栈
最后 弹出并输出栈顶元素 直到栈空
中缀转后缀算法2:
建表达式二叉树 后续遍历表达式树
建树方法:
1.优先级低 靠右的运算符离根近 优先优先级 同优先级优先靠右
2.自左向右使用数字 自左向右添加进叶节点中
后缀转中缀算法:
用表达式树 建树 中序遍历
ALL测试点AC的核心代码:
constexpr int MXN = 1e5 + 5;
char s[MXN];
stack<char> st;
queue<char> ans;
queue<str> q2;
bool CMP(char lhs, char rhs)
{
if (lhs == '*' || lhs == '/')
lhs = '2';
else
lhs = '1';
if (rhs == '*' || rhs == '/')
rhs = '2';
else
rhs = '1';
return lhs > rhs;
}
void Solve(void)
{
cin >> s + 1;
ll len = strlen(s + 1);
bool last = false;
str num = "";
ll cnt = 1;
bool othFlag = false;
char othChar;
FOR(i, 1, len)
{
if (('0' <= s[i] && s[i] <= '9') || s[i] == '.')
{
if (last)
num += s[i];
else
{
num = "";
num += s[i];
}
last = true;
if (i == len)
{
if (othFlag&&othChar=='-')
{
num = othChar + num;
othFlag = false;
}
q2.push(num);
ans.push('n');
}
cnt = 0;
}
else
{
if (s[i] == '(')
cnt = 1;
else if (s[i] == ')')
cnt = 0;
else
++cnt;
if (cnt == 2)
{
othFlag = true;
othChar = s[i];
continue;
}
if (last)
{
if (othFlag&&othChar=='-')
{
num = othChar + num;
othFlag = false;
}
q2.push(num);
ans.push('n');
}
last = false;
if (s[i] == '(')
st.push(s[i]);
else if (s[i] == ')')
while (!st.empty())
{
if (st.top() == '(')
{
st.pop();
break;
}
ans.push(st.top());
st.pop();
}
else
{
if (st.empty() || st.top() == '(')
st.push(s[i]);
else if (CMP(s[i], st.top()))
st.push(s[i]);
else
{
while (!st.empty() && st.top() != '(' && CMP(s[i], st.top()) == false)
{
ans.push(st.top());
st.pop();
}
st.push(s[i]);
}
}
}
}
while (!st.empty())
{
ans.push(st.top());
st.pop();
}
bool f = true;
while (!ans.empty())
{
if (f)
f = false;
else
cout << ' ';
if (ans.front() != 'n')
cout << ans.front();
else
{
cout << q2.front();
q2.pop();
}
ans.pop();
}
cout << edl;
return;
}