数据结构中对于栈的运用,最主要的一个例子就是简单表达式的计算了,当你独自将这个程序写出来的时候,这说明你对于栈的运用已经炉火纯青了,下面我将对这个问题做出详细的解答,让我们一起来看看吧
目录
【问题描述】
设计一个程序,实现简单整数的四则运算(运算对象不小于0),包括加减乘除和小括号。
【输入形式】
每行输入一个运算表达式(假设表达式均为正确的表达式),以#作为表达式结束。(表达式长度不超过80)
【输出形式】
输出表达式的后缀式
输出运算结果
【样例输入】
23-(2-4)*2+36/(20-14)#
(100-23)/6+2*(13-9)-40#
((100-20)*2)-35#
120+30+50#
【样例输出】
23 2 4 - 2 * - 36 20 14 - / +
33
100 23 - 6 / 2 13 9 - * + 40 -
-20
100 20 - 2 * 35 -
125
120 30 + 50 +
200
在方法一中呢我们定义两个主要函数,再在主函数中使用两个函数,最终求出表达式的值
一个函数用来求出原式子的后缀式
另一个函数用来进行后缀式的计算
后缀式的转换是个老生常谈的问题了,对于这个问题一定不能忘了要先设置运算符的优先级
- int f(char s){ //我们需要先设置运算符的优先级
- if(s=='#') return -1;
- else if(s=='('||s==')') return 0;
- else if(s=='+'||s=='-') return 1;
- else if(s=='*'||s=='/') return 2;
- }
- int Change(char *s1,char *s2){
- int i=0,e;
- PStack S;
- S=Init_Stack();
- Push_Stack(S,'#'); //初始化栈,置栈底为#
- while(*s1!='#'){ //因为输入#结束,所以最后一个输入的字符是#,当遇到#终止循环
- if(*s1>='0'&&*s1<='9'){ //遇到非运算符的时候
- while(*s1>='0'&&*s1<='9'){ //当有连续的非运算符,我们需要把他们放到一起
- s2[i++]=*s1;
- s1++;
- }
- s2[i++]=' '; //用空格将
-
-
-
- 不同元素隔开,方便后缀式的计算
- s1--; //这里的s1--千万不能少!!
- }else{ //当遇到运算符时
- Get_Stack(S,&e); //获取栈顶元素
- if((f(*s1)>f(e)&&*s1!=')')||*s1=='('){ //如果优先级大于栈顶元素且不是")"
- Push_Stack(S,*s1); //或者遇到了"(",直接入栈
- }else if(*s1==')'){ //如果读取的字符是")",先出栈,再判断
- Pop_Stack(S,&e);
- while(e!='('){ //遇到非"("的运算符放入后缀式
- s2[i++]=e; //遇到"("出栈后不用放到后缀式
- s2[i++]=' ';
- Pop_Stack(S,&e);
- }
- }else{ //当运算符优先级小于栈顶元素时,出栈放入后缀式直到大于栈顶元素
- while(f(*s1)<=f(e)){
- Pop_Stack(S,&e);
- s2[i++]=e;
- s2[i++]=' ';
- Get_Stack(S,&e);
- }
- Push_Stack(S,*s1); //入栈
- }
- }
- s1++;
- }
- while(!Empty_Stack(S)){ //将栈中剩余运算符都放入后缀式
- Pop_Stack(S,&e);
- s2[i++]=e;
- }
- int k=0;
- while(1){
- if(s2[k]=='#') break;
- printf("%c",s2[k++]); //打印后缀式
- }
- printf("\n");
- return 1;
- }
计算后缀式的方法是遍历后缀式,每遇到数字字符入栈,遇到运算符时从栈中取两个元素,进行计算,将计算结果放入栈中,用于下一次计算
- int Match(char *s){
- int a,b,x;
- PStack S;
- S=Init_Stack(); //初始化一个栈
- while(*s!='\0'){ //循环
- if(*s>='0'&&*s<='9'){ //当遇到数字字符时
- x=0;
- while(*s>='0'&&*s<='9'){ //使用此方法将字符串转换成整型变量,用于计算
- x=*s-'0'+x*10;
- s++;
- }
- Push_Stack(S,x); //入栈
- }else if(*s!=' '){ //当遇到非空格且不是数字字符时
- Pop_Stack(S,&a); //出栈一个数字
- Pop_Stack(S,&b); //再出栈一个数字
- switch(*s){ //进行运算,将运算结果放入栈中
- case '+':x=a+b;break;
- case '-':x=b-a;break;
- case '*':x=a*b;break;
- case '/':x=b/a;break;
- }
- Push_Stack(S,x);
- }
- s++;
- }
- Pop_Stack(S,&x); //最后出栈,打印最后一个元素即是表达式的解
- printf("%d",x);
- return 1;
- }
- #include
- #include
- typedef struct Stack{
- int data;
- struct Stack * next;
- }Stack,*PStack;
- PStack Init_Stack(){
- PStack S=(PStack)malloc(sizeof(Stack));
- S->next=NULL;
- return S;
- }
- int Empty_Stack(PStack S){
- if(!S->next) return 1;
- else return 0;
- }
- int Push_Stack(PStack S,int e){
- PStack P=(PStack)malloc(sizeof(Stack));
- P->data=e;
- P->next=NULL;
- P->next=S->next;
- S->next=P;
- return 1;
- }
- int Pop_Stack(PStack S,int *e){
- if(!S->next) return 0;
- *e=S->next->data;
- S->next=S->next->next;
- return 1;
- }
- int Get_Stack(PStack S,int *e){
- if(!S->next) return 0;
- *e=S->next->data;
- return 1;
- }
- int f(char s){
- if(s=='#') return -1;
- else if(s=='('||s==')') return 0;
- else if(s=='+'||s=='-') return 1;
- else if(s=='*'||s=='/') return 2;
- }
- int Change(char *s1,char *s2){
- int i=0,e;
- PStack S;
- S=Init_Stack();
- Push_Stack(S,'#');
- while(*s1!='#'){
- if(*s1>='0'&&*s1<='9'){
- while(*s1>='0'&&*s1<='9'){
- s2[i++]=*s1;
- s1++;
- }
- s2[i++]=' ';
- s1--;
- }else{
- Get_Stack(S,&e);
- if((f(*s1)>f(e)&&*s1!=')')||*s1=='('){
- Push_Stack(S,*s1);
- }else if(*s1==')'){
- Pop_Stack(S,&e);
- while(e!='('){
- s2[i++]=e;
- s2[i++]=' ';
- Pop_Stack(S,&e);
- }
- }else{
- while(f(*s1)<=f(e)){
- Pop_Stack(S,&e);
- s2[i++]=e;
- s2[i++]=' ';
- Get_Stack(S,&e);
- }
- Push_Stack(S,*s1);
- }
- }
- s1++;
- }
- while(!Empty_Stack(S)){
- Pop_Stack(S,&e);
- s2[i++]=e;
- }
- int k=0;
- while(1){
- if(s2[k]=='#') break;
- printf("%c",s2[k++]);
- }
- printf("\n");
- return 1;
- }
- int Match(char *s){
- int a,b,x;
- PStack S;
- S=Init_Stack();
- while(*s!='\0'){
- if(*s>='0'&&*s<='9'){
- x=0;
- while(*s>='0'&&*s<='9'){
- x=*s-'0'+x*10;
- s++;
- }
- Push_Stack(S,x);
- }else if(*s!=' '){
- Pop_Stack(S,&a);
- Pop_Stack(S,&b);
- switch(*s){
- case '+':x=a+b;break;
- case '-':x=b-a;break;
- case '*':x=a*b;break;
- case '/':x=b/a;break;
- }
- Push_Stack(S,x);
- }
- s++;
- }
- Pop_Stack(S,&x);
- printf("%d",x);
- return 1;
- }
- int main(){
- char s1[100],s2[100];
- scanf("%s",s1);
- Change(s1,s2);
- Match(s2);
- return 0;
- }
在方法二中我们只定义了一个计算函数,然后在主函数中边转换后缀式边进行计算(这样大大提高了计算效率)
我们设计一个计算函数,用于后缀式的计算
- int match(SqStack *s,char s2) //函数需要两个参量
- { //一个是栈,另一个是字符
- int a,b;
- ElemType e;
- switch(s2) //定义每一种字符的运算规则
- {
- case '+':
- GetTop(s,&b);
- Pop(s,&e);
- GetTop(s,&a);
- Pop(s,&e);
- Push(s,a+b);
- break;
- case '-':
- GetTop(s,&b);
- Pop(s,&e);
- GetTop(s,&a);
- Pop(s,&e);
- Push(s,a-b);
- break;
- case '*':
- GetTop(s,&b);
- Pop(s,&e);
- GetTop(s,&a);
- Pop(s,&e);
- Push(s,a*b);
- break;
- case '/':
- GetTop(s,&b);
- Pop(s,&e);
- GetTop(s,&a);
- Pop(s,&e);
- Push(s,a/b);
- break;
- case '#':break;
- }
- }
在主函数中,我们边进行后缀式转换,边进行表达式的计算,大大节省了程序运行的时间
- int main()
- {
-
- char s[100];
- while(gets(s))
- {
- SqStack s1,s2;
- InitStack(&s1); //第一个栈用于转换后缀式
- InitStack(&s2); //第二个栈用于计算后缀式
- Push(&s1,'#');
- int i;
- for(i=0;i
- {
- if(s[i]==')')
- {
- ElemType e;
- while(GetTop(&s1,&e)&&e!='(')
- {
- printf("%c ",e); //遇到字符进行运算
- match(&s2,e);
- Pop(&s1,&e); //取出这个字符
- }
- Pop(&s1,&e); //遇到"("时取出就好
- }
- else if(s[i]>='0'&&s[i]<='9') //遇到数字时
- {
- int x=0;
- while(s[i]>='0'&&s[i]<='9') //先将数字转换为整型
- {
- x=x*10+(s[i]-'0');
- i++;
- }
- Push(&s2,x); //将整型变量放入栈中,用于运算
- printf("%d ",x);
- i--;
- }
- else
- {
- ElemType e;
- if(s[i]!='(') //当你遇到的字符不是"("
- {
- while(GetTop(&s1,&e)&&f(s[i])<=f(e)) //且运算符优先级小于栈顶元素
- {
- if(e!='#')printf("%c ",e);
- match(&s2,e); //执行运算
- Pop(&s1,&e); //取出栈顶元素,继续下一次判断
- }
- }
- Push(&s1,s[i]); //直到优先级大于栈顶元素,入栈
- }
- }
- int m;
- GetTop(&s2,&m); //栈中最后只剩栈底元素"#"和最后一个值,最后一个值就是表达式结果
- printf("\n%d",m);
- }
- return ERROR;
- }
1.3 完整代码
- #include
- #include
- #include
- #include
- #define ERROR 0
- #define OK 1
- typedef int ElemType;
- typedef struct StackNode
- {
- ElemType data;
- struct StackNode *next;
- }StackNode,*SqStack;
- int InitStack(SqStack *s)
- {
- (*s)=NULL;
- return OK;
- }
- int EmptyStack(SqStack *s)
- {
- if(*s==NULL) return OK;
- else return ERROR;
- }
- int Push(SqStack *s,ElemType e)
- {
- SqStack p;
- p=(SqStack)malloc(sizeof(StackNode));
- p->data=e;
- p->next=*s;
- *s=p;
- return OK;
- }
- int Pop(SqStack *s,ElemType *e)
- {
- if(*s==NULL)
- return ERROR;
- else
- {
- SqStack p;
- p=*s;
- *e=p->data;
- *s=(*s)->next;
- free(p);
- return OK;
- }
- }
- int GetTop(SqStack *s,ElemType *e)
- {
- if(*s==NULL)
- return ERROR;
- else
- {
- *e=(*s)->data;
- return OK;
- }
- }
- int f(char s2)
- {
- if(s2=='#') return -1;
- else if(s2=='(') return 0;
- else if(s2=='+'||s2=='-') return 1;
- else if(s2=='*'||s2=='/') return 2;
- }
- int match(SqStack *s,char s2)
- {
- int a,b;
- ElemType e;
- switch(s2)
- {
- case '+':
- GetTop(s,&b);
- Pop(s,&e);
- GetTop(s,&a);
- Pop(s,&e);
- Push(s,a+b);
- break;
- case '-':
- GetTop(s,&b);
- Pop(s,&e);
- GetTop(s,&a);
- Pop(s,&e);
- Push(s,a-b);
- break;
- case '*':
- GetTop(s,&b);
- Pop(s,&e);
- GetTop(s,&a);
- Pop(s,&e);
- Push(s,a*b);
- break;
- case '/':
- GetTop(s,&b);
- Pop(s,&e);
- GetTop(s,&a);
- Pop(s,&e);
- Push(s,a/b);
- break;
- case '#':break;
- }
- }
- int main()
- {
-
- char s[100];
- while(gets(s))
- {
- SqStack s1,s2;
- InitStack(&s1);
- InitStack(&s2);
- Push(&s1,'#');
- int i;
- for(i=0;i
- {
- if(s[i]==')')
- {
- ElemType e;
- while(GetTop(&s1,&e)&&e!='(')
- {
- printf("%c ",e);
- match(&s2,e);
- Pop(&s1,&e);
- }
- Pop(&s1,&e);
- }
- else if(s[i]>='0'&&s[i]<='9')
- {
- int x=0;
- while(s[i]>='0'&&s[i]<='9')
- {
- x=x*10+(s[i]-'0');
- i++;
- }
- Push(&s2,x);
- printf("%d ",x);
- i--;
- }
- else
- {
- ElemType e;
- if(s[i]!='(')
- {
- while(GetTop(&s1,&e)&&f(s[i])<=f(e))
- {
- if(e!='#')printf("%c ",e);
- match(&s2,e);
- Pop(&s1,&e);
- }
- }
- Push(&s1,s[i]);
- }
- }
- int m;
- GetTop(&s2,&m);
- printf("\n%d",m);
- }
- return ERROR;
- }
运行结果

附:系列文章
-
相关阅读:
微服务架构的外部 API 集成模式
JAVA毕业设计二手车商城计算机源码+lw文档+系统+调试部署+数据库
算法--差分
java导出Mysql表信息生成Word文档
前端vue element axios混编团队发送数据到后端,后端接受使用的是$_POST
Android 导入ncnn-android-yolov8-seg : 实现人体识别和人像分割
华为路由器升级系统文件
错误模块路径: ...\v4.0.30319\clr.dll,v4.0.30319 .NET 运行时中出现内部错误,进程终止,退出代码为 80131506。
java毕业设计研究生实验室综合管理系统Mybatis+系统+数据库+调试部署
根文件系统介绍
-
原文地址:https://blog.csdn.net/m0_68111267/article/details/127121720