数据结构与算法之-----栈的应用(三)
【
写在前面的话:本专栏的主要内容:数据结构与算法。
1.对于初识数据结构的小伙伴们,鉴于后面的数据结构的构建会使用到专栏前面的内容,包括具体数据结构的应用,所使用到的数据结构,也是自己构建的,未使用系统的库文件,因此,建议这类小伙伴们从本专栏的总揽按顺序进行学习;
2.对于想查询有关资料的小伙伴们,可以选择性地浏览。希望小伙伴们都能有所收获~
】
本章为栈的第三个应用:
问题描述:如何计算一个字符串表达式的值?
咱也可以从另一个角度来认识这个问题:
------如何制作一个简易的计算器?
实际上,要想实现一个计算器的功能,是一个非常复杂的问题,
下面我们将问题简化一下,假设此表达式中,
运算符只有:“+”,“-”,“*”,“/”,阶乘,方幂这六种再加上括号,
于是,我们有以下的栈结构实现(EvaluAlgor.h):
本质来说,该算法并不算完善,读者可以思考一下,该算法中存在什么问题?
/** 作者:易果啥笔* 时间:2021.8.20* 内容:栈的典型应用三:求一个字符串表达式的数值**/#ifndef STACK_EVALUALGOR_H
#define STACK_EVALUALGOR_H
#define N_OPTR 9 //运算符总数
#include "Stack.h"
#include <cmath>
#include "ParenMatch.h"typedef enum {ADD,SUB,MUL,DIV,POW,FAC,L_P,R_P,EOE} Operator;//将运算符与上述枚举对应
Operator optrRank(char optr){switch (optr) {case '+' : return ADD;case '-' : return SUB;case '*' : return MUL;case '/' : return DIV;case '^' : return POW;case '!' : return FAC;case '(' : return L_P;case ')' : return R_P;case '\0' : return EOE;default: exit(-1);}
}//pri[]数组用于描述不同运算符之间的优先级关系
const char pri[N_OPTR][N_OPTR] = {'>','>','<','<','<','<','<','>','>','>','>','<','<','<','<','<','>','>','>','>','>','>','<','<','<','>','>','>','>','>','>','<','<','<','>','>','>','>','>','>','>','<','<','>','>','>','>','>','>','>','>',' ','>','>','<','<','<','<','<','<','<','=',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','<','<','<','<','<','<','<',' ','=',
};//readNumber()用于获取从某数字字符开始的完整一个数void readNumber(char*& S,Stack<float>& p){p.push((float)(*S-'0'));while(isdigit(*(++S)))p.push(p.pop()*10+(*S-'0')); //整数部分,注意到 '123' - '0' = 123if('.' != *S) return;float xiaoshu = 1;while(isdigit(*(++S)))p.push(p.pop()+(*S-'0')*(xiaoshu/=10)); //小数部分
}//orderBetween()用于判定操作符之间的优先级关系
char orderBetween(char optr1,char optr2){return pri[optrRank(optr1)][optrRank(optr2)]; //直接比较
}//calcu()函数用于求一个(阶乘)或两个数的运算//先求阶乘
int factorial(int n){if(n<0)exit(-1);else if(n == 1) return 1;else return n*factorial(n-1); //递归实现
}int calcu(char optr,int pOpnd){return factorial(pOpnd); }//重载calcu()方法使之适用于两个数之间的运算float calcu(float pOpnd1,char optr,float pOpnd2) {if (optr == '/' && pOpnd2 == 0) exit(-1); //除数不能为零switch (optr) {case '+' :return pOpnd1 + pOpnd2;break;case '-' :return pOpnd1 - pOpnd2;break;case '*' :return pOpnd1 * pOpnd2;break;case '/' :return pOpnd1 / pOpnd2;break;case '^' :return pow(pOpnd1, pOpnd2); //借用cmath库中的求幂函数pow()default:exit(-1);}
}//evaluate()为求值核心算法float evaluate(char *S) {if( ! paren(S,0,length(S)) ) exit(-1); //不匹配时else{Stack<float> opnd;Stack<char> optr; //运算符栈,操作符栈optr.push('\0');while (!optr.Empty()) {if (isdigit(*S)) {readNumber(S, opnd);} elseswitch (orderBetween(optr.top(), *S)) {case '<':optr.push(*S);S++;break;case '=':optr.pop();S++;break;case '>':char op = optr.pop();if ('!' == op) {float pOpnd = opnd.pop();if ((int) pOpnd == pOpnd) {opnd.push(calcu(op, (int) pOpnd));} else exit(-1); //小数没有阶乘} else {float pOpnd2 = opnd.pop(), pOpnd1 = opnd.pop();opnd.push(calcu(pOpnd1, op, pOpnd2));}break;}}return opnd.pop();}}#endif //STACK_EVALUALGOR_H
在evaluate()数值求解算法中,先使用了Paren()方法验证括号是否匹配。Paren()方法参考我的上一篇博文。此外,请读者细细体会栈在这种算法中所起的作用。
在main.cpp文件中我们可以验证它的正确性:
/** 作者:易果啥笔* 时间:2021.8.20* 内容:栈的应用**/#include <iostream>
#include "Stack.h"
#include "ParenMatch.h"
#include "EvaluAlgor.h"using namespace std;//遍历函数print
template <typename T> void print(T& e){ cout<<e; };int main() {//应用三:求一个字符串表达式的值char expression2[40] = "10^3+23/2-(56*7)+5!";cout<<"10^3+23/2-(56*7)+5!表达式的值为:"<<evaluate(expression2)<<" "<<(10*10*10+23/2.0-(56*7)+5*4*3*2*1)<<endl;return 0;
}
仔细思考,你可以发现,这个算法是不支持负数参与计算的,这也是我前文所说的问题所在。读者可以思考一下,如何修改代码,使之支持负数参与运算。
欲了解栈的其他应用,点击传送门跳转:
1. 栈的应用(一)
2. 栈的应用(二)
下一章:数据结构与算法之-----队列
数据结构与算法之-----栈的应用(三)相关推荐
- 数据结构与算法之栈入门题目
数据结构与算法之栈题目 目录 用数组实现大小固定的队列和栈 实现一个特殊的栈,在实现栈的基础功能上,再实现返回栈中最小元素的操作 如果仅用栈结构实现队列结构和如何仅用队列结构实现栈结构 1. 用数组实 ...
- 数据结构与算法--简单栈实现及其应用
栈 栈(Stack)是一种限制插入和删除只能在一个位置上进行的表,改位置是表的末端,叫做栈顶top.栈的基本操作有push (进栈)pop(出栈) 栈又叫做LIFO(后进先出)表,下图展示普通push ...
- C++数据结构和算法2 栈 双端/队列 冒泡选择插入归并快排 二三分查找 二叉树 二叉搜索树 贪婪 分治 动态规划
C++数据结构和算法2 栈 双端/队列 冒泡选择插入归并快排 二三分查找 二叉树 二叉搜索树 贪婪 分治 动态规划 博文末尾支持二维码赞赏哦 _ github 章3 Stack栈 和 队列Queue= ...
- 数据结构与算法--利用栈实现队列
利用栈实现队列 上一节中说明了栈的特点 后进先出,我们用数组的方式实现了栈的基本操作api,因此我们对栈的操作是不考虑排序的,每个api的操作基本都是O(1)的世界,因为不考虑顺序,所以找最大,最小值 ...
- 数据结构与算法(Python)第三天
数据结构与算法(Python)第三天 3:链表 为什么需要链表 链表的定义 3.1 单向链表 Python 中赋值的实际意义: 节点实现 单链表的操作 单链表的实现 测试 链表与顺序表的对比 3:链表 ...
- 新星计划Day7【数据结构与算法】 栈Part1
新星计划Day7[数据结构与算法] 栈Part1
- 数据结构与算法(2)——栈和队列
前言:题图无关,只是好看,接下来就来复习一下栈和队列的相关知识 前序文章: 数据结构与算法(1)--数组与链表(https://www.jianshu.com/p/7b93b3570875) 栈 什么 ...
- 【数据结构与算法】栈与队列
栈 一.什么是栈? 1.后进者先出,先进者后出,这就是典型的"栈"结构. 2.从栈的操作特性来看,是一种"操作受限"的线性表,只允许在端插入和删除数据. 二.为 ...
- 数据结构与算法之-----栈的应用(二)
[ 写在前面的话:本专栏的主要内容:数据结构与算法. 1.对于初识数据结构的小伙伴们,鉴于后面的数据结构的构建会使用到专栏前面的内容,包括具体数据结构的应用,所使用到的数据结构,也是自己 ...
最新文章
- AI4U:以用户友好为目标,智源重大研究方向“机器学习”学者候选人发布
- classification_report进阶:针对top-k的结果计算precision@k、recall@k、f1-score@k
- 芬兰计算机研究生申请表,芬兰的研究生申请技巧
- bccomp在php中什么意思,PHP bccomp()用法及代码示例
- TensorFlow Serving + Docker + Tornado机器学习模型生产级快速部署
- Java单层循环实现输出九九乘法表
- SAP FSM 学习笔记(二) : SAP FSM的微信接入
- php_os用法,golang中os包用法
- 小动画制作 图片盒子配合定时器 winform 114869633
- 向服务器上传本地大文件的方法xshell
- 36.5. height / width
- linux iconv命令详解,iconv命令
- cad导出pdf_CAD如何导出高分辨率图片
- ffmpeg php 使用教程_php的ffmpeg - CSDN博客
- csm和uefi_【一点资讯】关于CSM和UEFI你要知道的一些事 www.yidianzixun.com
- MySQL技术:数据库逻辑结构单元
- 前端基础——html5新增标签
- 湘潭大学计算机分数线,湘潭大学录取分数线2021是多少分(附历年录取分数线)
- android高德地图上加自定义菜单,自定义UI控件-UI界面定制-开发指南-Android 导航SDK | 高德地图API...
- matlab求解微分方程解析解