【问题描述】
给定一个四则运算的中缀表达式,编程计算表达式的值。基本要求:
(1)在给定的表达式中要包含括号;
(2)栈的操作要求自己完成,不允许调用类库中的方法;
(3)对不同的操作编写相应的函数。
【算法思想】
算法的核心思想的对四则运算符赋予数字优先级来比较大小,对输入的字符串扫描,将运算符和数字分别压入各自栈中。然后类似与二叉树的后序遍历对表达式进行求值。
如果栈顶运算符优先级低,新运算符直接入栈
如果栈顶运算符优先级大于等于此时的优先级,先出栈计算,新运算符再入栈
如果遇到括号,左括号直接入栈,等遇到右括号时一直计算到一个左括号到栈顶时
时间复杂度为O(len(str)),整个字符串只需要扫描一遍
可以先看下方竞赛写法,然后自己用那个思想写出实训方法
实训写法:
#includeusing namespace std; #define OK 1 #define ERROR 0 #define MAXSIZE 100 #define INFEASIBLE -1 #define OVERFLOW -2 typedef int Status; typedef struct{ char *top; char *base; int stacksize; }SqStack; Status InitStack(SqStack &S){ S.base=(char *)malloc(MAXSIZE*sizeof(char)); if(!S.base) exit(OVERFLOW); S.top=S.base; S.stacksize=MAXSIZE; return OK; } Status ShowStack(SqStack S){//遍历运算符栈 if(S.base==S.top) return ERROR; while(S.top!=S.base){ cout<<*(S.top-1)< =MAXSIZE) { puts("运算符栈满了,需要追加"); S.base=(char *)realloc(S.base,(S.stacksize+10)*sizeof(char)); //栈满的时候,追加 10个存储空间 if(!S.base) exit(OVERFLOW); puts("追加成功!"); S.top=S.base+S.stacksize; S.stacksize+=10; } *S.top=ch; S.top++; return OK; } char GetTop(SqStack S){return *(S.top-1);}//运用该函数之前已经判断栈不为空了,所以此处直接取即可 Status Pop(SqStack &S,char &ch){ if(S.base==S.top) return ERROR; ch=*(S.top-1); S.top--; return OK; } Status StackEmpty(SqStack S){ if(S.base==S.top) return true; return false; } typedef struct{ double *top; double *base; int stacksize; }StackNum; Status InitStackNum(StackNum &S){ S.base=(double *)malloc(MAXSIZE*sizeof(double)); if(!S.base) exit(OVERFLOW); S.top=S.base; S.stacksize=MAXSIZE; return OK; } Status ShowStackNum(StackNum S){//遍历数值栈 if(S.base==S.top) return ERROR; while(S.top!=S.base){ cout<<*(S.top-1)< =MAXSIZE) { puts("数值栈满了,需要追加"); S.base=(double *)realloc(S.base,(S.stacksize+10)*sizeof(double)); //栈满的时候,追加 10个存储空间 if(!S.base) exit(OVERFLOW); puts("追加成功!"); S.top=S.base+S.stacksize; S.stacksize+=10; } *S.top=e; S.top++; return OK; } Status PopNum(StackNum &S,double &e){ if(S.base==S.top) return ERROR; e=*(S.top-1); S.top--; return OK; } double GetTopNum(StackNum S){ if(S.base==S.top) return false; return *(S.top-1); } int PriorityLevel(char ch){//返回运算符优先级大小 “此程序的经典所在 ” switch(ch){ case '+': return 1; case '-': return 1; case '*': return 2; case '/': return 2; case '(': return 0;//因为我们不需要‘(’进行数值运算,所以给它最低的权限 } } Status IsNum(char ch){//判断是否是数字 if(ch>='0'&&ch<='9') return OK; return ERROR; } Status IsOpr(char ch){//判断是否是运算符 if(ch=='+'||ch=='-'||ch=='*'||ch=='/') return OK; return ERROR; } SqStack opr; StackNum num;//为了操作方便定义为全局变量 void eval(){ double b;PopNum(num,b);//因为表达式的先后输入,我们要计算a/b,此时在栈顶的是b; double a;PopNum(num,a); char op;Pop(opr,op); double res; if(op=='/') res=a/b; if(op=='*') res=a*b; if(op=='-') res=a-b; if(op=='+') res=a+b; PushNum(num,res); return ; } Status Input(){ char *str; str=(char *)malloc(MAXSIZE*sizeof(char)); InitStack(opr); InitStackNum(num); puts("请输入表达式并以回车结束 :"); gets(str); for(int i=0;i =PriorityLevel(ch)) eval(); Push(opr,ch); } else{ puts("您的输入有问题请重新输入"); return ERROR; } } while(!StackEmpty(opr)) eval(); return OK; } void OutAns(){ puts("运算结果为:"); printf("%gn",GetTopNum(num)); } void IntroDuce(){ system("color F3"); puts("----------------------Writen By AsUs---------------------"); puts("------------------------2021.12.14-----------------------"); puts("-------------------欢迎使用表达式计算程序----------------"); puts("-------------------该程序仅支持四则运算------------------"); puts("------------------------加 减 乘 除----------------------"); } void Message(){ puts("以上既为本次运算结果"); putchar('n'); puts("1.继续使用该程序"); puts("2.退出该程序"); putchar('n'); puts("你的选择为:"); int id=0; while(id!=1&&id!=2){ scanf("%d",&id); if(id==1) system("cls"); else if(id==2) exit(0); else puts("输入指令错误请重新输入!"); } getchar(); } void Init(){ InitStack(opr); InitStackNum(num); } int main(){ while(true){ Init(); IntroDuce(); Input(); OutAns(); Message(); } return 0; }
竞赛写法:
#includeusing namespace std; stack op; stack num; map pr; //unordered_map pr{ {'+', 1}, {'-', 1}, {'*',2}, {'/', 2} }; void eval(){ int b=num.top();num.pop(); int a=num.top();num.pop(); char c=op.top();op.pop(); int x; if(c=='+') x=a+b; if(c=='-') x=a-b; if(c=='/') x=a/b; if(c=='*') x=a*b; num.push(x); return ; } int main(){ pr['+']=1; pr['-']=1; pr['*']=2; pr['/']=2; string s; cin>>s; for(int i=0;i =pr[c]) eval(); op.push(c); } } while(op.size()){ eval(); } cout<



