一、后缀表达式

1、理解

对于算术表达式来说,其基本规则是:先乘除,后加减;先括号内,再括号外;相同优先级情况下从左到右。比如,5 + 6 / 2 - 3 * 4 就是一个算术表达式,它的正确理解应该是:5 + 6 / 2 - 3 * 4 = 5 + 3 - 3 * 4 = 8 - 12 = -4。可以看出这类表达式主要由两类对象构成的,即运算数和运算符号。

我们先来分析一类仅由两种运算符号和三个运算数构成的相对简单的算术表达式,比如2 + 3 * 4或2 * 3 + 4,其基本形式是a1 op1a2op2a3,其中ai为运算数,opi为运算符号。

当计算机编译程序分析这样的表达式,一般就是从左到右扫描。当扫描了a1op1a2找到两个运算数一个运算符号后,并设法做出是否马上进行运算的决定。因为还需要看op2的优先级是否比op1高。所以,编译程序从左往右扫描时,需要根据前后运算优先级的情况决定;先保留当前数据和运算符号,还是马上进行计算。比如,对于2 + 3 * 4,当扫描了2 + 3后还不能做出计算2 + 3的决定,因为后面" * "的优先级比" + "高,所以必须先将2 、3以及" + "保留起来,等到后面合适机会时再将这些数据和运算符号拿来运算。所以,需要有一种数据结构能够很好地实现对等待运算或数据的组织。

为了更容易理解表达式的求值方法,我们分析一下更简单的一种表达式:后缀表达式。平常我们经常使用的表达式是中缀表达式,即运算符号位于两个运算数之间的表达式。而在后缀表达式中,运算符号位于两个运算数之后。比如,前面提到常量表达式5 + 6 / 2 - 3 * 4的后缀形式就是:5 6 2 / + 3 4 * - 。还有一种表达式形式叫前缀表达式,运算符号位于两个运算数之前。比如,5 + 6 / 2 - 3 * 4的前缀形式就是:- + 5 / 6 2 * 3 4。

可见,后缀表达式运算数出现的顺序与相应中缀表达式一样,但运算符出现在不同的位置。

后缀表达式相对比中缀表达式的求值要容易得多。我们先来看一下,后缀表达式5 6 2 / + 3 4 * -如何求解。

同样,我们还是从左到右扫描这个表达式,求解过程如下。

(1)遇见运算数5 6 2时均不做计算,同时记住这个序列5 6 2。

(2)当遇见运算符号" / "时,把最近遇到的两个数6和2从序列中取出作运算,并把结果3放到刚才那个序列的后面,即当前序列为:5 3。

(3)当遇见运算符号" + "时,把序列的最后两个数 5 和 3 取出作运算,并把结果8放到当前的序列的后面,因而当前序列为:8。

(4)遇见 3 4 时均不做计算,把这两个数放到当前序列的后面,因为当前序列为8 3 4.

(5)当遇见运算符号" * "时,把当前序列的最后两个数 3 和 4 取出作运算,并把结果12放到当前序列的后面,因而当前序列为:8 12。

(6)当遇见运算符号" - "时,把当前的最后两个数 8 和 12 取出作运算,并把结果 -4 放到当前序列的后面,因而当前序列为:-4。

(7)当输入中不再有符号时,当前序列中的值(-4)就是表达式的结果值。

2、题目

题目1:(后缀表达式)

题目描述

所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。

如:3*(5–2)+7对应的后缀表达式为:3.5.2.-*7.+@。’@’为表达式的结束符号。‘.’为操作数的结束符号。

输入格式:

后缀表达式

输出格式:

表达式的值

输入输出样例

输入:

3.5.2.-*7.+@

输出:

16

说明提示:

字符串长度,1000内。

AC代码:

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int N = 1e3 + 10;ll stk[N];int main()
{ll top = 0, now = 0;char op;while((op = getchar()) != '@'){// 数字if(op >= '0' && op <= '9'){now *= 10;now += op - '0';}else if(op == '.'){stk[++ top] = now;now = 0;}else if(op == '+'){stk[top - 1] += stk[top];stk[top] = 0;top --;}else if(op == '-'){stk[top - 1] -= stk[top];stk[top] = 0;top --;}else if(op == '*'){stk[top - 1] *= stk[top];stk[top] = 0;top --;}else if(op == '/'){stk[top - 1] /= stk[top];stk[top] = 0;top --;}}printf("%lld",stk[1]);return 0;
}

题目2:(表达式的转换:中缀转后缀)

题目描述:

平常我们书写的表达式称为中缀表达式,因为它将运算符放在两个操作数中间,许多情况下为了确定运算顺序,括号是不可少的,而中缀表达式就不必用括号了。

后缀标记法:书写表达式时采用运算紧跟在两个操作数之后,从而实现了无括号处理和优先级处理,使计算机的处理规则简化为:从左到右顺序完成计算,并用结果取而代之。

例如:8-(3+2*6)/5+4可以写为:8 3 2 6*+5/-4+

其计算步骤为:

8 3 2 6 * + 5 / – 4 +
8 3 12 + 5 / – 4 +
8 15 5 / – 4 +
8 3 – 4 +
5 4 +
9

编写一个程序,完成这个转换,要求输出的每一个数据间都留一个空格。

输入格式:

就一行,是一个中缀表达式。输入的符号中只有这些基本符号0123456789+-*/^(),并且不会出现形如2*-3的格式。

表达式中的基本数字也都是一位的,不会出现形如12形式的数字。

所输入的字符串不要判错。

输出格式:

若干个后缀表达式,第I+1行比第I行少一个运算符和一个操作数,最后一行只有一个数字,表示运算结果。

样例:

输入:

8-(3+2*6)/5+4

输出:

8 3 2 6 * + 5 / - 4 +
8 3 12 + 5 / - 4 +
8 15 5 / - 4 +
8 3 - 4 +
5 4 +
9

说明/提示:

运算的结果可能为负数,/以整除运算。并且中间每一步都不会超过2 ^ 31。字符串长度不超过100。

思路:

这题最麻烦的就是把中缀表达式转化成后缀表达式,难点是处理优先级的问题。 我们从左往右扫描中缀表达式,进行如下处理:

1.

建立一个符号栈op和一个存后缀表达式的字符串p。

2.

如果是数字则加入p,因为形为"A  op  B"的中缀表达式转成后缀表达式就成了"A  B  op" , 数字一定在前。

3.

如果是左括号,则加入符号栈op。

4.

如果是右括号,则把符号栈中的运算符弹到s,直到遇到最近的左括号。最后,把一个左括号删除(不入p)。

5.

如果是运算符,则把优先级大于或等于的栈顶符号弹入p。因为这样能保证优先级高的先算。

为什么,优先级等于也要弹出呢?因为同级运算从左往右啊。

6.

重复2~5,直到扫描完毕。

7.

把剩下的符号依次弹入p。

AC代码:

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int N = 1e3 + 10;//思路:把中缀表达式转成后缀表达式,再对后缀表达式进行处理。
//每处理一次运算,把数值栈中的数字输出,并把未处理的符号、数字输出。 char s[N];//中缀表达式
ll val[N];int top;//数值栈
stack<char>op;//符号栈
char p[N];int p_top;//postfix Expression 后缀表达式int grade(char op)//优先级
{if(op == '+' || op == '-')  return 1; // +,-优先级最低,用1表示if(op == '*' || op == '/')  return 2; // 其次是×,/,用2表示if(op == '^')  return 3; // ^优先级最高,用3表示else  return 0; // 此处可不写,防止报错
}void calc(char op)//计算
{ll x = val[top --], y = val[top];switch(op){case '+':y+=x;break;case '-':y-=x;break;case '*':y*=x;break;case '/':y/=x;break;case '^':y=pow(y,x);}val[top]=y;
}int main()
{scanf("%s",s);int n = strlen(s);for(int i = 0 ; i < n ; i ++){if(s[i] >= '0' && s[i] <= '9')  p[++ p_top] = s[i]; //数字直接加入后缀表达式,因为形为"A  op  B"的中缀表达式转成后缀表达式就成了"A  B  op" , 数字一定在前 else{//括号if(s[i] == '(' )  op.push(s[i]); // 左括号加入符号栈else if(s[i] == ')') // 如果是右括号 {while(!op.empty() && (op.top()) != '(' ) // 符号栈不空并且符号栈的栈顶元素不为左括号{p[++ p_top] = op.top(); // op.pop(); // 弹出符号栈的栈顶元素}op.pop(); // 弹出符号栈的左括号}else//运算符 {while(!op.empty() && grade(op.top()) >= grade(s[i])) // 符号栈不空当前符号栈的栈顶元素的优先级大于等于当前枚举的元素{p[++ p_top] = op.top(); // 符号栈的栈顶元素加入后缀表达式op.pop(); // 弹出符号栈的栈顶元素}op.push(s[i]); // 将该运算符加入符号栈}}}while(!op.empty()) // 当符号栈不为空的时候{p[++ p_top] = op.top(); // 将符号栈的栈顶元素加入后缀表达式op.pop(); // 弹出符号栈的栈顶元素}for(int i = 1 ; i <= p_top ; i ++)  printf("%c ",p[i]); // 输出每个阶段的后缀表达式puts("");//输出中缀表达式for(int i = 1 ; i <= p_top ; i ++) //逐步处理后缀表达式 {if(p[i] >= '0' && p[i] <= '9')  val[++ top] = p[i] - '0'; // else//运算符 {calc(p[i]);for(int j = 1 ; j <= top ; j ++) printf("%lld ",val[j]);for(int j = i + 1 ; j <= p_top ; j ++) printf("%c ",p[j]);puts("");    }}return 0;
}

后缀表达式、中缀表达式相关推荐

  1. 六十四、前缀,后缀,中缀表达式转化求值问题

    @Author:Runsen 编程的本质来源于算法,而算法的本质来源于数学,编程只不过将数学题进行代码化. ---- Runsen 算法,一门既不容易入门,也不容易精通的学问. 上次介绍如何利用栈实现 ...

  2. 数据结构前缀,后缀,中缀表达式

    [cpp] view plain copy   [cpp] view plain copy   <span style="color: rgb(51, 51, 51); font-fa ...

  3. 255.0.0.0子网掩码相应的cidr前缀表示法是?_六十四、前缀,后缀,中缀表达式转化求值问题...

    「@Author:Runsen」 ❝ 编程的本质来源于算法,而算法的本质来源于数学,编程只不过将数学题进行代码化. 「---- Runsen」 ❞ 算法,一门既不容易入门,也不容易精通的学问. 上次介 ...

  4. 前缀表达式/中缀表达式/后缀表达式

    前缀表达式/中缀表达式/后缀表达式 中缀表达式就是平常的表达式,如(3+4)*5-6=29 前缀表达式又称为波兰式,也就是运算符位于数字前面,如 -*+3456 后缀表达式又称为逆波兰式,也就是运算符 ...

  5. 前缀表达式中缀表达式后缀表达式之间的转换JAVA代码实现

    一.前缀表达式 (1)中缀表达式转前缀表达式 (2)前缀表达式的计算 二.后缀表达式 (1)中缀表达式转后缀表达式 (2)后缀表达式的计算 三.中缀表达式直接计算 四.总结 代码实现的工具类Expre ...

  6. (数据结构)前缀,后缀以及中缀表达式

    中缀表达式(中缀记法) 中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间.中缀表达式是人们常用的算术表示方法. 前缀表达式(前缀记法.波兰式) 前缀表达式是一种没有括号的 ...

  7. 逆波兰表达式中缀表达式转换为后缀表达式

    中缀表达式转换为后缀表达式 思路分析 代码实现 package com.atguigu.stack;import javax.swing.plaf.nimbus.State; import java. ...

  8. 后缀转中缀表达式_中缀转后缀表达式代码实现(下)及计算器完整版

    南故笙烟:中缀表达式转为后缀表达式​zhuanlan.zhihu.com 思路分析 1.初始化两个栈:运算符栈s1和储存中间结果的栈s2 2.从左至右扫描中缀表达式 3.遇到操作数时,将其压入s2 4 ...

  9. python中缀转后缀_中缀表达式转后缀表达式Python

    中缀表达式转后缀表达式参考的文章就是直接给出了算法,但是算法如何推导出来的还没有弄明白,简单记录下我自己的理解,强行解释一下. 后缀表达式就是操作符再操作数的后面,并且计算机能够根据简单的优先级就能进 ...

  10. java中缀表达式转后缀表达式_数据结构Java实现06----中缀表达式转换为后缀表达式...

    本文主要内容: 表达式的三种形式 中缀表达式与后缀表达式转换算法 一.表达式的三种形式: 中缀表达式:运算符放在两个运算对象中间,如:(2+1)*3.我们从小做数学题时,一直使用的就是中缀表达式. 后 ...

最新文章

  1. mysql开启慢查询日志
  2. ng-repeat根据多个字段排序
  3. R语言可视化斜率图、扩充图像纵横比为数据标签显示更整齐、ggrepel包来帮忙
  4. phpcms v9 为分类和内容添加伪静态
  5. ajax 更新模型数据_PyTorch视觉工具包torchvision重大更新!支持各种检测模型、分割模型,还有许多数据集...
  6. 【入门建议收藏】密码学学习笔记之线性分析入门篇——EzSPN
  7. linux java编译后生成文件_Linux终端编译并执行Java文件
  8. 【笔试题】C语言结构体中,不同的数据类型在32位和64位下所占字节的区别
  9. mysql中sql批量插入_sql中insert如何批量插入多条记录?
  10. c/c++ linux 进程 fork wait函数
  11. netty LEAK: ByteBuf.release() was not called before it's garbage-collected
  12. fluent瞬态计算终止条件在哪里设置_基于商用软件FLUENT的LES(大涡模拟)计算教学...
  13. python爬取音乐下载_Python爬取全抖音好听背景音乐,一次性下载
  14. 齿轮的正负变位设计要点
  15. css美化浏览器默认滚动条样式
  16. oracle 11g xdb.,Oracle 11g升级到11.2.0.3过程中XDB.DBMS_XMLSCHEMA相关报错
  17. MathType安装时遇到不能删除xx字体时的解决方法
  18. 光格科技递交科创板上会稿:拟募资6亿 预计年营收3亿
  19. kubernetes集群搭建Zabbix监控平台
  20. 初识vue的使用和设计模式

热门文章

  1. 如何选购阿里云服务器并快速入门(Windows版本)?
  2. 江苏海洋大学计算机考试系统,江苏海洋大学教务管理系统入口https://jwc.hhit.edu.cn/...
  3. APM固件自动巡航车测评与SLAM路径规划
  4. 一站式linux0.11内核head.s代码段图表详解
  5. windows访问虚拟机DNS服务器,windows虚拟机中DNS服务配置
  6. 数值优化:一阶和二阶优化算法(Pytorch实现)
  7. NAT代理服务器技术调研
  8. 字符串?=字符+\0
  9. C# 中的CTS、ClS、ClR的用途
  10. 如何选择我的搜索引擎关键字?