第16课-栈的应用实战二

1. 问题的提出

计算机的本质工作就是数学运算,那计算机可以读入字符串”9 + (3 - 1) *5 +8/2”并且计算值吗?

2. 后缀表达式

波兰科学家在20世纪50年代提出了一种将运算符放在数字后面的后缀表达式。

对应的,我们平时用的数学表达式叫做中缀表达式。

实例

5 + 3 => 5 3 +

1 + 2 * 3 => 1 2 3 * +

9 + ( 3–1 ) * 5 => 9 3 1–5 * +

中缀表达式符合人类的阅读和思维习惯;后缀表达式符合计算机的“运算习惯”。

3. 解决方案

遍历中缀表达式中的数字和符号。

对于数字:直接输出 。

对于符号:

左括号:进栈

符号:与栈顶符号进行优先级比较,栈顶符号优先级低:进栈

栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈 ,之后进栈

右括号:将栈顶符号弹出并输出,直到匹配左括号

遍历结束:将栈中的所有符号弹出并输出。

4. 整体框架

transform(exp)

{

创建栈 s;

i = 0;

while(exp[i] != '\0')

{

if(exp[i]为数字)

{

Output(exp[i]);

}

else if(exp[i]为符号)

{

while(exp[i]优先级 <= 栈顶符号优先级)

{

output(栈顶优先级);

Pop(S);

}

Push(S,exp[i]);

}

else if(exp[i]为右括号)

{

while(栈顶符号不为括号)

{

output(栈顶符号);

Pop(S);

}

}

从S中弹出左括号;

else

{

报错,停止循环;

}

i++;

}

while((Size(S) > 0)&&(exp[i]=='\0'))

{

output(栈顶符号);

Pop(S);

}

}

5. 中缀转后缀的算法

#include <stdio.h>

#include "LinkStack.h"

int isNumber(char c)

{

return ('0' <= c) && (c <= '9');

}

int isOperator(char c)

{

return (c == '+') || (c == '-') || (c == '*') || (c == '/');

}

int isLeft(char c)

{

return (c == '(');

}

int isRight(char c)

{

return (c == ')');

}

int priority(char c)

{

int ret = 0;

if( (c == '+') || (c == '-') )

{

ret = 1;

}

if( (c == '*') || (c == '/') )

{

ret = 2;

}

return ret;

}

void output(char c)

{

if( c != '\0' )

{

printf("%c", c);

}

}

void transform(const char* exp)

{

LinkStack* stack = LinkStack_Create();

int i = 0;

while( exp[i] != '\0' )

{

if( isNumber(exp[i]) )

{

output(exp[i]);

}

else if( isOperator(exp[i]) )

{

while( priority(exp[i]) <= priority((char)(int)LinkStack_Top(stack)) )

{

output((char)(int)LinkStack_Pop(stack));

}

LinkStack_Push(stack, (void*)(int)exp[i]);

}

else if( isLeft(exp[i]) )

{

LinkStack_Push(stack, (void*)(int)exp[i]);

}

else if( isRight(exp[i]) )

{

char c = '\0';

while( !isLeft((char)(int)LinkStack_Top(stack)) )

{

output((char)(int)LinkStack_Pop(stack));

}

LinkStack_Pop(stack);

}

else

{

printf("Invalid expression!");

break;

}

i++;

}

while( (LinkStack_Size(stack) > 0) && (exp[i] == '\0') )

{

output((char)(int)LinkStack_Pop(stack));

}

LinkStack_Destroy(stack);

}

int main()

{

transform("9+(3-1)*5+8/2");

printf("\n");

return 0;

}

6. 计算机的计算习惯

计算机对后缀表达式的运算是基于栈的

解决方案:

遍历后缀表达式中的数字和符号

对于数字:进栈

对于符号:

从栈中弹出右操作数

从栈中弹出左操作数

根据符号进行运算

将运算结果压入栈中

便利结束:栈中的唯一数字为计算结果

7. 算法框架

compute(exp)

{

创建栈 S;

i = 0;

while(exp[i] != '\0')

{

if(exp[i] 为数字)

{

Push(S,exp[i]);

}

else if(exp[i]为符号)

{

1、丛栈中弹出右操作数;

2、从栈中弹出左操作数;

3、根据符号进行运算;

4、Push(stack,结果);

}

else

{

报错,停止循环;

}

i++;

}

if((Size(S) == 1) && (exp[i] == '\0'))

{

栈中唯一的数字为运算结果;

}

返回结果;

}

程序:

#include <stdio.h>

#include "LinkStack.h"

int isNumber(char c)

{

return ('0' <= c) && (c <= '9');

}

int isOperator(char c)

{

return (c == '+') || (c == '-') || (c == '*') || (c == '/');

}

int value(char c)

{

return (c - '0');

}

int express(int left, int right, char op)

{

int ret = 0;

switch(op)

{

case '+':

ret = left + right;

break;

case '-':

ret = left - right;

break;

case '*':

ret = left * right;

break;

case '/':

ret = left / right;

break;

default:

break;

}

return ret;

}

int compute(const char* exp)

{

LinkStack* stack = LinkStack_Create();

int ret = 0;

int i = 0;

while( exp[i] != '\0' )

{

if( isNumber(exp[i]) )

{

LinkStack_Push(stack, (void*)value(exp[i]));

}

else if( isOperator(exp[i]) )

{

int right = (int)LinkStack_Pop(stack);

int left = (int)LinkStack_Pop(stack);

int result = express(left, right, exp[i]);

LinkStack_Push(stack, (void*)result);

}

else

{

printf("Invalid expression!");

break;

}

i++;

}

if( (LinkStack_Size(stack) == 1) && (exp[i] == '\0') )

{

ret = (int)LinkStack_Pop(stack);

}

else

{

printf("Invalid expression!");

}

LinkStack_Destroy(stack);

return ret;

}

int main()

{

printf("9 + (3 - 1) * 5 + 8 / 2 = %d\n", compute("931-5*+82/+"));

return 0;

}

小结:

中缀表达式是人习惯的表达方式。

后缀表达式是计算机喜欢的表达方式。

通过栈可以方便的将中缀形式变换为后缀形式。

中缀表达式的计算过程类似程序编译运行的过程。

转载于:https://www.cnblogs.com/free-1122/p/11322780.html

数据-第16课-栈的应用实战二相关推荐

  1. 牛客网SQL实战二刷 | 完整解析 -- 目录索引

    「牛客网SQL实战二刷」是个系列学习笔记博文,Day1 - Day10,每天解析6道SQL题目- 初衷是留给自己一份笔记,也希望能分享给「一起学习SQL的你」? 每篇笔记的格式大致为,三大板块: 大纲 ...

  2. flutter 项目实战二 网络请求

    本项目借用 逛丢 网站的部分数据,仅作为 flutter 开发学习之用. 逛丢官方网址:https://guangdiu.com/ flutter windows开发环境设置 flutter 项目实战 ...

  3. 第16课 Altium Designer20(AD20)+VESC6.4实战教程:总体布局和定义板子边框 (第一版)(北冥有鱼)

    第16课 Altium Designer20(AD20)+VESC6.4实战教程:总体布局和定义板子边框 (第一版)(北冥有鱼)

  4. 虚拟现实数字沙盘三维电子沙盘元宇宙大数据人工智能无人机倾斜摄影三维全景建模第16课

    虚拟现实数字沙盘三维电子沙盘元宇宙大数据人工智能无人机倾斜摄影三维全景建模第16课 新增加属性在MTGIS3d控件 public bool ShowFLGrid;//是否显 示方里网格. public ...

  5. Spark商业案例与性能调优实战100课》第16课:商业案例之NBA篮球运动员大数据分析系统架构和实现思路

    Spark商业案例与性能调优实战100课>第16课:商业案例之NBA篮球运动员大数据分析系统架构和实现思路 http://www.basketball-reference.com/leagues ...

  6. 电子沙盘数字沙盘大数据可视化GIS系统开发教程第16课

    电子沙盘数字沙盘大数据可视化GIS系统开发教程第16课:新增加属性在MTGIS3d控件 public bool ShowFLGrid;//是否显 示方里网格. public bool Atmosphe ...

  7. 汇编语言将数据、代码、栈放入不同段基础

    Code内部逻辑: Start 初始化各段寄存器 入栈 出栈 物理逻辑: 代码实现: assume cs:code, ds:data, ss:stack; // 代码段cs.数据段ds.栈段ssdat ...

  8. 汇编语言中将数据、代码、栈放入不同的段

    数据.代码.栈放入不同的段 在学习汇编语言,将数据.代码.栈放入不同的段.参考王爽老师的<汇编语言>第四版,对P133的汇编代码,进行了个人理解标注.仅供参考,存在错误之处,请大家斧正. ...

  9. 16课:关于Springboot和@Cacheable注解拉去缓存,@CacheEvict清空缓存的原理

    16课:关于Springboot和@Cacheable注解拉去缓存,@CacheEvict清空缓存的原理 简介 代码展示 1.pox.xml 2.application.properties文件 3. ...

  10. 大数据入门第一课 Hadoop基础知识与电商网站日志数据分析

    大数据入门第一课 Hadoop基础知识与电商网站日志数据分析 本课程从Hadoop核心技术入手,以电商项目为依托,带领你从0基础开始上手,逐步掌握大数据核心技术(如:HDFS.YARN.MapRedu ...

最新文章

  1. 浅谈对主成分分析(PCA)算法的理解
  2. 用Numpy搭建神经网络第二期:梯度下降法的实现
  3. 因主机名更改造成oracle控制台登录错误:ora-12545,ora-12541
  4. 封装的可运行于winform与web的Log4Net的类库
  5. C语言实现UDP网络通信(附服务端和客服端完整源码)
  6. Spring Boot中使用MyBatis注解配置详解
  7. Java语言用于定义接口的关键字是_定义类的保留字是(__)定义接口的保留字是(__);...
  8. 【Pre蓝桥杯嵌入式】【STM32】学习索引
  9. libguestfs java_libguestfs实现原理summary
  10. 【玩转开源】BananaPi R2——移植RPi.GPIO 到 R2
  11. 检查pdf字体是否全部嵌入
  12. bzoj4399: 魔法少女LJJ(线段树合并)
  13. IntelliJ IDEA 2018.3 安装+永久激活[Windows]
  14. android 目录作用,Android中各级目录的作用说明
  15. springboot启动 lombok 找不到符号
  16. 小学生计算机应用手抄报,小学生科技手抄报大全
  17. STM32的BootLoader 从SD卡更新固件
  18. 【大数据处理】广州餐饮店铺爬虫并可视化,上传至hdfs
  19. TypeError: unbound method a() must be called with A instance as first argument (got nothing instead)
  20. Windows、Linux系统常用CMD命令大全

热门文章

  1. 将数组A中的内容和数组B中的内容进行交换,计算1/1-1/2+1/3-1/4+1/5 …… + 1/99 - 1/100 的值,1到 100 的所有整数中出现多少次数字9。
  2. Android 代码中的常见的问题总结
  3. java selenium sleep_【转】java-selenium三种等待方式
  4. Call for Presentations!Flink Forward Global 2021 议题征集ing
  5. 华为鸿蒙系统老手机能用吗_华为发布鸿蒙2.0手机开发者测试版!华为老手机可申请公测...
  6. 5个好用的搜索小技巧:搜索引擎的办法
  7. 学习scrapy使用
  8. 2层框架结构柱子间距_钢筋混凝土楼板层其施工方法有哪些不同
  9. mysql-proxy 读写分离_mysql 基于mysql-proxy实现读写分离
  10. php请求图片,PHP - 发送GET请求并获取图片作为回报