要求:如:(a*b)+c/d应输入(*)+/
输出*+/
a+b/(c-d)应输入+/(-)
输出+/(-)
a+(b+c)应输入+(+)
输出++
看到括号我们首先想到用栈解决,且应想到符号的优先级,即“ * ”,“ / ” > " + ", " - "
由于去除括号的情况需要同时考虑左括号左边符号,右括号右边符号对括号内部的影响,较麻烦,故直接考虑括不去除括号情况,即:左括号左侧为“ - ”或“ * ”且括号内部存在+
或-
时不可去括号, 左括号左侧符号“ / ”不可去括号,* ( )
:括号右侧为“ * ”或“ / ”且括号内存在+
或-
时不可去括号
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
stack<int> sta;
vector<PII> v;
string s;
map<char, int> signlevel;
sta
,用于存储左括号的位置, v
,用于存储括号的配对信息。 signlevel
,用于存储不同符号的优先级。
bool check(int a, int b) {
stack<int> tmp;
vector<char> sign;
char leftsign = s[a-1], rightsign = s[b+1];
int mnlv = 3;
int rslv = signlevel[rightsign];
tmp
临时栈,用于判断是否处于内部括号范围内。sign
,用于存储括号内的符号。char leftsign = s[a-1], rightsign = s[b+1]
获取括号左边的符号和右边的符号。mnlv = 3
表示括号内符号优先级最低的初始值。rslv
获取右边符号的优先级。
for(int i = a+1;i <= b-1;i ++) {
if(s[i] == ' ') continue;
if(tmp.empty()) {
if(s[i] == '(') tmp.push(1);
else if(!isalpha(s[i])) sign.push_back(s[i]);
} else if(s[i] == ')') tmp.pop();
}
for(int i = 0;i < sign.size();i ++)
mnlv = min(mnlv, signlevel[sign[i]]);
循环遍历sign
向量,找到括号内符号的最低优先级
if(mnlv < rslv) return false;
if(((leftsign == '-' || leftsign == '*') && mnlv != 2) || leftsign == '/')
return false;
return true;
}
如果括号内符号的最低优先级小于右边符号的优先级,或者左边符号是-
或*
且括号内符号最低优先级不是 2,或者左边符号是/
,则返回false
;否则返回true
。
int main()
{
signlevel[' '] = 0; signlevel['('] = 0; signlevel[')'] = 0;
signlevel['+'] = 1; signlevel['-'] = 1; signlevel['*'] = 2; signlevel['/'] = 2;
初始化符号优先级。空格、左括号和右括号的优先级为 0,加号和减号的优先级为 1,乘号和除号的优先级为 2。
while(cin>>s) {
v.clear();
int n = s.size();
s = ' '+s+' ';
for(int i = 1;i <= n;i ++)
if(s[i] == '(') sta.push(i);
else if(s[i] == ')') v.push_back(PII(i, sta.top())), sta.pop();
sort(v.begin(), v.end());
for(int i = 0;i < v.size();i ++) {
int a = v[i].second, b = v[i].first;
if(check(a, b)) s[a] = s[b] = ' ';
}
for(int i = 1;i <= n;i ++) if(s[i] != ' ') cout << s[i]; puts("");
}
}
遍历,调用check
函数判断是否可以去括号,如果可以,则将括号对应的字符设置为空格。遍历字符串,输出非空格字符,即去除括号后的表达式。
o(*▽*)q
多多支持呀╰(*°▽°*)╯
收起