题目链接
看到题目,毫无疑问,这是道大模拟+栈。
对于中缀表达式,不做任何处理来计算出结果是十分麻烦的,所以我利用了刚刚学的栈来转换成后缀表达式来做。
将中缀表达式转换为后缀表达式,遵循如下法则:
-
遇到数字,直接将数字输出;
-
遇到运算符,比较其与栈顶的优先级,如果栈顶运算符的优先级比当前运算符高,则一直输出并弹出栈顶元素直到栈顶的优先级比当前运算符低为止(或者遇到正括号了),将运算符压入。
-
遇到正括号,直接压入,遇到反括号,持续弹出运算符直到遇到最近的正括号为止,然后弹出正括号,但正反括号均不输出。(注意:遇到N/(A*B+C)这种情况时,弹出的乘号是直接输出,而非转换后存在括号里)
最后注意把运算符弹出完。
代码如下
#include <bits/stdc++.h>
using namespace std;
string str;
char sc[100005];//运算符栈
map<char,int>a;//运算符优先级映射
struct node{
int type;//type为1表示运算符,type为0表示数字
int num;
}st[200005];//存储后缀表达式
int top=0,toc=0;
int main() {
a['+']=1;//定义优先级
a['-']=1;
a['*']=2;
a['/']=2;
a['^']=3;
cin>>str;
for(int i=0;i<str.size();i++){
if(str[i]<='9'&&str[i]>='0'){//转换数字
int sum=0;
while(str[i]<='9'&&str[i]>='0'){
sum=sum*10+str[i]-'0';
i++;
}
i--;
st[++top].type=0;
st[top].num=sum;//直接输出
}else{
switch(str[i]){
case '(':{//正括号
sc[++toc]=str[i];
break;
}
case ')':{//反括号
while(sc[toc]!='('){
st[++top].type=1;
st[top].num=(int)sc[toc];
toc--;
}
toc--;
break;
}
default:{//运算符
while(a[sc[toc]]>=a[str[i]]&&sc[toc]!='('){
st[++top].type=1;
st[top].num=(int)sc[toc];
toc--;
}
sc[++toc]=str[i];
break;
}
}
}
/*
for(int j=1;j<=toc;j++){
cout<<sc[j];
}
cout<<endl;
for(int j=1;j<=top;j++){
if(st[j].type==0){
cout<<st[j].num;
}else{
cout<<(char)st[j].num;
}
}
cout<<endl;
getchar();
*/
}
while(toc){//记得弹出
st[++top].type=1;
st[top].num=(int)sc[toc];
toc--;
}
/*
for(int i=1;i<=top;i++){
if(st[i].type==0){
cout<<st[i].num<<' ';
}else{
cout<<(char)st[i].num<<' ';
}
}
cout<<endl;
*/
return 0;
}
然后是将后缀表达式计算出来,对于计算机而言,后缀表达式没有优先级之类麻烦的东西,可以大胆地去算。运算法则如下:
- 如果遇到数字,直接压入栈中。
- 如果遇到运算符,将栈顶两个元素弹出进行计算,再将计算的结果压入栈中。(注意:减法、除法、乘方是有先后顺序的,切记不可搞错)。
代码如下
#include <bits/stdc++.h>
using namespace std;
string str;
struct node{
int type;
int num;
}st[200005];
int num[100005];
int top=0,ton=0;
int main() {
for(int i=1;i<=top;i++){
if(st[i].type==0){
num[++ton]=st[i].num;//数字入栈
}else{
int x,y,z;
switch((char)st[i].num){//字符计算
case '+':{
x=num[ton--];
y=num[ton];
z=x+y;
num[ton]=z;
break;
}
case '-':{
x=num[ton--];
y=num[ton];
z=y-x;//注意顺序
num[ton]=z;
break;
}
case '*':{
x=num[ton--];
y=num[ton];
z=x*y;
num[ton]=z;
break;
}
case '/':{
x=num[ton--];
y=num[ton];
z=y/x;//注意顺序
num[ton]=z;
break;
}
case '^':{
x=num[ton--];
y=num[ton];
z=pow(y,x);//注意顺序
num[ton]=z;
break;
}
}
}
/*
for(int i=1;i<=ton;i++){
cout<<num[i]<<' ';
}
cout<<endl;
getchar();
*/
}
cout<<num[1];//最后的结果即为数字栈顶
return 0;
}
最后总的代码就是这样了:
100分AC代码:
#include <bits/stdc++.h>
using namespace std;
string str;
char sc[100005];
map<char,int>a;
struct node{
int type;
int num;
}st[200005];
int num[100005];
int top=0,toc=0,ton=0;
int main() {
a['+']=1;
a['-']=1;
a['*']=2;
a['/']=2;
a['^']=3;
cin>>str;
for(int i=0;i<str.size();i++){
if(str[i]<='9'&&str[i]>='0'){
int sum=0;
while(str[i]<='9'&&str[i]>='0'){
sum=sum*10+str[i]-'0';
i++;
}
i--;
st[++top].type=0;
st[top].num=sum;
}else{
switch(str[i]){
case '(':{
sc[++toc]=str[i];
break;
}
case ')':{
while(sc[toc]!='('){
st[++top].type=1;
st[top].num=(int)sc[toc];
toc--;
}
toc--;
break;
}
default:{
while(a[sc[toc]]>=a[str[i]]&&sc[toc]!='('){
st[++top].type=1;
st[top].num=(int)sc[toc];
toc--;
}
sc[++toc]=str[i];
break;
}
}
}
/*
for(int j=1;j<=toc;j++){
cout<<sc[j];
}
cout<<endl;
for(int j=1;j<=top;j++){
if(st[j].type==0){
cout<<st[j].num;
}else{
cout<<(char)st[j].num;
}
}
cout<<endl;
getchar();
*/
}
while(toc){
st[++top].type=1;
st[top].num=(int)sc[toc];
toc--;
}
/*
for(int i=1;i<=top;i++){
if(st[i].type==0){
cout<<st[i].num<<' ';
}else{
cout<<(char)st[i].num<<' ';
}
}
cout<<endl;
*/
for(int i=1;i<=top;i++){
if(st[i].type==0){
num[++ton]=st[i].num;
}else{
int x,y,z;
switch((char)st[i].num){
case '+':{
x=num[ton--];
y=num[ton];
z=x+y;
num[ton]=z;
break;
}
case '-':{
x=num[ton--];
y=num[ton];
z=y-x;//注意
num[ton]=z;
break;
}
case '*':{
x=num[ton--];
y=num[ton];
z=x*y;
num[ton]=z;
break;
}
case '/':{
x=num[ton--];
y=num[ton];
z=y/x;//注意
num[ton]=z;
break;
}
case '^':{
x=num[ton--];
y=num[ton];
z=pow(y,x);//注意
num[ton]=z;
break;
}
}
}
/*
for(int i=1;i<=ton;i++){
cout<<num[i]<<' ';
}
cout<<endl;
getchar();
*/
}
cout<<num[1];
return 0;
}
大功告成!