【问题描述】

给定一个四则运算的中缀表达式,编程计算表达式的值。基本要求:
(1)在给定的表达式中要包含括号;
(2)栈的操作要求自己完成,不允许调用类库中的方法;
(3)对不同的操作编写相应的函数。

【算法思想】
算法的核心思想的对四则运算符赋予数字优先级来比较大小,对输入的字符串扫描,将运算符和数字分别压入各自栈中。然后类似与二叉树的后序遍历对表达式进行求值。
如果栈顶运算符优先级低,新运算符直接入栈
如果栈顶运算符优先级大于等于此时的优先级,先出栈计算,新运算符再入栈
如果遇到括号,左括号直接入栈,等遇到右括号时一直计算到一个左括号到栈顶时
时间复杂度为O(len(str)),整个字符串只需要扫描一遍

可以先看下方竞赛写法,然后自己用那个思想写出实训方法

实训写法:

#include<bits/stdc++.h>
using 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)<<endl;S.top--;}return OK;
}
Status Push(SqStack &S,char ch){if(S.top-S.base>=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)<<endl;S.top--;}return OK;
}
Status PushNum(StackNum &S,double e){if(S.top-S.base>=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<strlen(str);i++){char ch=str[i];if(IsNum(ch)){int j=i;int numb=0;while(IsNum(str[j])) numb=numb*10+(str[j++]-'0');PushNum(num,numb);i=j-1;}else if(ch=='(') Push(opr,ch);else if(ch==')'){while(true){char t;int NewNum;if(StackEmpty(opr)) break;t=GetTop(opr);if(t=='('){Pop(opr,t);break;}else Eval();}}else if(IsOpr(ch)){//Push该运算符之前,应该把栈顶优先级比他大的运算符计算掉 while(!StackEmpty(opr)&&PriorityLevel(GetTop(opr))>=PriorityLevel(ch)) Eval();Push(opr,ch);}else{puts("您的输入有问题请重新输入");return ERROR;}}while(!StackEmpty(opr)) Eval(); return OK;
}
void OutAns(){puts("运算结果为:");printf("%g\n",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;
}

竞赛写法:

#include<bits/stdc++.h>
using namespace std;
stack<char>op;
stack<int>num;
map<char,int>pr;
//unordered_map<char, int> 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<s.size();i++){char c=s[i];if(isdigit(c)){int x=0;int j=i;while(j<s.size()&&isdigit(s[j])) x=x*10+(s[j++]-'0');i=j-1;num.push(x);}else if(c=='(') op.push(c);else if(c==')'){while(op.size()&&op.top()!='(') eval();op.pop();}else{while(op.size()&&pr[op.top()]>=pr[c]) eval();op.push(c);}}while(op.size()){eval();}cout<<num.top()<<endl;return 0;
} 

数据结构实训《表达式求值》相关推荐

  1. c语言程序设计报告表达式求值,数据结构 课程设计表达式求值 实验报告

    <数据结构 课程设计表达式求值 实验报告>由会员分享,可在线阅读,更多相关<数据结构 课程设计表达式求值 实验报告(21页珍藏版)>请在人人文库网上搜索. 1.实验课程名称 级 ...

  2. java求值不用后缀表达式_数据结构之后缀表达式求值(java实现)

    数据结构之后缀表达式求值(java实现) 前记 ​ 今天在刷leet code的时候刷到了一道题,后缀表达式(逆波兰表达式)求值,我花了一会儿写了一下它的解法.但是今天我不谈什么是后缀表达式,有兴趣的 ...

  3. linux算术表达式求值数据结构,数据结构:算数表达式求值演示

    题目:设计一个程序,演示用算符优先法对算数表达式求值的过程. 一.需求分析 以字符序列的形式从终端读入输入语法正确.不含变量的整数表达式.利用教科书表3.1给出的算符优先关系,实现对算数四则混合运算表 ...

  4. 常考数据结构与算法:表达式求值

    题目描述 请写一个整数计算器,支持加减乘三种运算和括号. 示例2 输入 "(2*(3-4))*5" 返回值 -10 运算符号有优先级,所以使用单调栈可以解决改问题.如下代码,效率比 ...

  5. 数据结构—— 基于二叉树的算术表达式求值

    实验五 基于二叉树的算术表达式求值 数据结构--中序表达式求值(栈实现) 实验目的: 1.掌握二叉树的二叉链表存储表示和二叉树的遍历等基本算法. 2.掌握根据中缀表达式创建表达式树的算法 3.掌握基于 ...

  6. 编程题实训-实验2-基于栈的算术表达式求值算法(北京林业大学)

    第1关:基于栈的中缀算术表达式求值 任务描述 本关任务:输入一个中缀算术表达式,求解表达式的值.运算符包括+.-.*./.(.).=,参加运算的数为double类型且为正数.(要求:直接针对中缀算术表 ...

  7. [数据结构]表达式求值

    一.问题描述 表达式求值是数学中的一个基本问题,也是程序设计中的一个简单问题.我们所涉及的表达式中包含数字和符号,本实验中处理的符号包括'+'.'-'.'*'.'/'.'('和')',要求按照我们所习 ...

  8. python数据结构和算法 时间复杂度分析 乱序单词检测 线性数据结构 栈stack 字符匹配 表达式求值 queue队列 链表 递归 动态规划 排序和搜索 树 图

    python数据结构和算法 参考 本文github 计算机科学是解决问题的研究.计算机科学使用抽象作为表示过程和数据的工具.抽象的数据类型允许程序员通过隐藏数据的细节来管理问题领域的复杂性.Pytho ...

  9. 数据结构 - 拓展突破(C++实现中缀表达式转前缀表达式,中缀表达式转后缀表达式,前缀表达式求值,中缀表达式求值)

    文章目录 1. C++中缀表达式转后缀表达式 2. C++中缀表达式转前缀表达式 3. C++后缀表达式求值 4. C++前缀表达式求值 1. C++中缀表达式转后缀表达式 输入中缀表达式样例: 2+ ...

  10. python前缀表达式求值_python数据结构与算法 11 后缀表达式求值

    从本节开始,删除原版的英文,直接发译后的文稿. 后缀表达式求值 栈的最一个应用例子,计算一个后缀表达式的值.这个例子中仍然用栈的数据结构.不过,当扫描表达式的时候,这次是操作数压栈等待,不是转换算法中 ...

最新文章

  1. 给GridView增加求和行
  2. MySQL 5.1以下如何动态抓取查询日志
  3. 在 Mac OSX 版的 LispBox 环境上安装配置 SBCL 详细过程
  4. 算法艺术——网络最大流
  5. 第一次上计算机课日记500,第一次上网课作文500字
  6. 7 Steps for becoming Deep Learning Expert
  7. oracle隐藏游标,Oracle 存储过程隐藏游标
  8. 面试中关于String、StringBuffer、StringBuilder的频率最高问题
  9. 权限管理系统2_权限表,权限模块表
  10. 吴恩达深度学习之四《卷积神经网络》学习笔记
  11. python2.7使用TimeDelta中total_seconds()方法的问题
  12. 一些散落各处的移动开发好资源
  13. C++公有、私有、保护继承的关系
  14. Google IO 2018 来啦!
  15. 远程采集Linux硬盘信息,关关采集器利用远程SFTP采集 Linux放主站+windows采集教程...
  16. 网络舆情监测关键词怎么设置与搜集的方法技巧
  17. php mktime 2037,phpmktime计算两时间之差_PHP教程
  18. PDF.JS PDF文件预览插件
  19. oracle11g本地安装,windows64位机oracle11g+pl/sql安装教程图解
  20. python爬虫爬取图片详解_Python使用爬虫爬取静态网页图片的方法详解

热门文章

  1. launch计算机上哪个初中,这位妈妈10年夏校经验告诉你:小学初中高中都该如何选择夏校?...
  2. 使用TIMESTAMPDIFF计算两个时间戳之间的时间间隔需要注意的细节
  3. 决策树的三种常见算法
  4. 【微信公众号开发】四、公众号按钮设置及自己的微信按钮编辑器
  5. 自然语言处理 文本数据分析
  6. iPhone播放声音文件的例子
  7. AcWing 188. 武士风度的牛
  8. android ue设计原则,ued设计原则
  9. 辗转取余数php算最小公约数,JS取得最小公倍数与最大公约数
  10. 威斯康星麦迪逊计算机专业排名,威斯康星大学麦迪逊分校计算机工程排名