Python与数据结构[1] -> 栈/Stack[1] -> 中缀表达式与后缀表达式的转换和计算
中缀表达式与后缀表达式的转换和计算
目录
1 中缀表达式转换为后缀表达式
中缀表达式转换为后缀表达式的实现方式为:
- 依次获取中缀表达式的元素,
- 若元素为操作数(数字/字母等),则加入后缀表达式中
- 若元素为操作符,则压入栈中,此时对比入栈操作符与栈内元素的计算等级,等级大于或等于入栈元素的栈内操作符都将被弹出栈,加入到后缀表达式中
- 左括号直接入栈,优先级最高,不弹出栈内元素
- 右括号不入栈,而是弹出所有元素加入后缀表达式,直至遇见匹配的左括号,并弹出左括号但不加入后缀表达式中
- 当中缀表达式的元素耗尽后,依次弹出栈内元素加入到后缀表达式中。
代码实现过程如下,
完整代码
from linked_list_stack import Stack
SIGN = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 3}
def infix_to_postfix(expr):
global SIGN
out = []
s = Stack()
for i in expr:
if i in SIGN.keys():
# Pop all high level sign except left bracket
while s.top():
if SIGN[s.top()] < SIGN[i] or s.top() == '(':
break
out.append(s.pop())
# Push sign
s.push(i)
elif i == ')':
# Pop all sign until left bracket encountered
while s.top() != '(':
out.append(s.pop())
# Pop left bracket
s.pop()
else:
# Push number
out.append(i)
while s.top():
out.append(s.pop())
return out
if __name__ == '__main__':
ep = 'a + b * c + ( d * e + f ) * g'
print(' '.join(infix_to_postfix(ep.split(' '))))
分段解释
首先从链表栈中导入栈类,并定义各个操作符的优先级
from linked_list_stack import Stack
SIGN = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 3}
接着定义转换函数,
- 函数接受一个中缀表达式的可迭代对象,创建列表out存放后缀表达式,以及一个空栈s
- 随后开始遍历中缀表达式,判断遍历元素的类型,若为操作数则加入out,
- 若为右括号则依次弹出栈内元素加入out列表,直到遇见左括号,弹出左括号不加入out,
- 若为普通操作符则压入栈中,并对比栈内操作符优先级,依次弹出高优先级或相同优先级的操作符,
- 遍历结束后依次弹出栈内元素,最后返回后缀表达式的字符串形式。
def infix_to_postfix(expr):
global SIGN
out = []
s = Stack()
for i in expr:
if i in SIGN.keys():
# Pop all high level sign except left bracket
while s.top():
if SIGN[s.top()] < SIGN[i] or s.top() == '(':
break
out.append(s.pop())
# Push sign
s.push(i)
elif i == ')':
# Pop all sign until left bracket encountered
while s.top() != '(':
out.append(s.pop())
# Pop left bracket
s.pop()
else:
# Push number
out.append(i) while s.top():
out.append(s.pop())
return out if __name__ == '__main__':
ep = 'a + b * c + ( d * e + f ) * g'
print(' '.join(infix_to_postfix(ep.split(' '))))
最后可以得到表达式输出结果为
a b c * + d e * f + g * +
2 后缀表达式的计算
后缀表达式的计算过程其实也是后缀转换为中缀的一个过程:
- 首先依次遍历后缀表达式,
- 当元素为操作数时,压入栈中,
- 当元素为操作符时,弹出栈内最顶上的两个元素,进行操作运算,将得到的结果再次压入栈中,
- 直到后缀表达式遍历结束,此时栈内只有唯一的一个元素即最终的运算结果,弹出栈即可
实现的过程十分简单,具体代码如下,其中中缀表达式转后缀表达式的方法为前面定义的方法
完整代码
from linked_list_stack import Stack
SIGN = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 3}
def postfix_calc(expr):
global SIGN
s = Stack()
for i in expr:
if i in SIGN.keys():
right = str(s.pop())
left = str(s.pop())
cal = ' '.join((left, i, right))
# cal = ' '.join([str(s.pop()), i, str(s.pop())][::-1])
s.push(eval(cal))
else:
s.push(i)
return s.pop()
if __name__ == '__main__':
ep = '( ( 2 + 3 ) * 8 + 5 + 3 ) * 6'
print(eval(ep))
print(postfix_calc(infix_to_postfix(ep.split(' '))))
ep = '3 + ( 2 * 9 ) / 2 * ( 3 + 6 ) * 7'
print(eval(ep))
print(postfix_calc(infix_to_postfix(ep.split(' '))))
最后测试直接运算中缀表达式和中缀转后缀后再计算得到的结果,两者结果相同。
288
288
570.0
570.0
Python与数据结构[1] -> 栈/Stack[1] -> 中缀表达式与后缀表达式的转换和计算的更多相关文章
- Python与数据结构[1] -> 栈/Stack[0] -> 链表栈与数组栈的 Python 实现
栈 / Stack 目录 链表栈 数组栈 栈是一种基本的线性数据结构(先入后出FILO),在 C 语言中有链表和数组两种实现方式,下面用 Python 对这两种栈进行实现. 1 链表栈 链表栈是以单链 ...
- C语言- 基础数据结构和算法 - 09 栈的应用_中缀表达式转后缀表达式20220611
09 栈的应用_中缀表达式转后缀表达式20220611 听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/ ...
- 数据结构(3) 第三天 栈的应用:就近匹配/中缀表达式转后缀表达式 、树/二叉树的概念、二叉树的递归与非递归遍历(DLR LDR LRD)、递归求叶子节点数目/二叉树高度/二叉树拷贝和释放
01 上节课回顾 受限的线性表 栈和队列的链式存储其实就是链表 但是不能任意操作 所以叫受限的线性表 02 栈的应用_就近匹配 案例1就近匹配: #include <stdio.h> in ...
- 利用stack结构,将中缀表达式转换为后缀表达式并求值的算法实现
#!/usr/bin/env python # -*- coding: utf-8 -*- # learn <<Problem Solving with Algorithms and Da ...
- 中缀表达式得到后缀表达式(c++、python实现)
将中缀表达式转换为后缀表达式的算法思想如下: 从左往右开始扫描中缀表达式 遇到数字加入到后缀表达式 遇到运算符时: 1.若为‘(’,入栈 2.若为’)‘,把栈中的运算符依次加入后缀表达式,直到出现'( ...
- 中缀表达式转后缀表达式(Python实现)
中缀表达式转后缀表达式 中缀表达式转后缀表达式的规则: 1.遇到操作数,直接输出: 2.栈为空时,遇到运算符,入栈: 3.遇到左括号,将其入栈: 4.遇到右括号,执行出栈操作,并将出栈的元素输出,直到 ...
- 栈的简单应用之中缀表达式转后缀表达式(C语言实现逆波兰式)
一.前言 普通人在书写计算式时会选择中缀表达式,这样符合人脑的认知习惯.可计算机处理时后缀表达式才能使处理速度更快,其原因是利用堆栈结构减少计算机内存访问.同时它也是一个很好锻炼栈这个数据结构的应 ...
- 栈的应用实例——中缀表达式转换为后缀表达式
声明:本程序读入一个中缀表达式,将该中缀表达式转换为后缀表达式并输出后缀表达式. 注意:支持+.-.*./.(),并且输入时每输入完一个数字或符号都要加一个空格,特别注意的是在整个表达式输入完成时也要 ...
- 【Weiss】【第03章】练习3.20:中缀表达式转后缀表达式
[练习3.20] a.编写一个程序将中缀表达式转换为后缀表达式,该中缀表达式含括号及四则运算. b.把幂操作符添加到你的指令系统中去. c.编写一个程序将后缀表达式转化为中缀表达式. Answer: ...
随机推荐
- Vbs 测试程序三
一段被写滥了的VBS代码 值得一提的是感兴趣的同学可以把 chr(13) + chr(13) + chr(13) 改为chr(11) + chr(11) + chr(11) 不赘述 on error ...
- CSS系列(5)-如何使用Firebug查看网页的html和css
Firebug是火狐浏览器Firefox的一个插件,专门为开发人员开发的.使用Firebug需要先在Firefox中安装这个插件,网上有很多教程,可以对照着安装一下. 不同的火狐浏览器版本中的Fire ...
- 恢复误删除表黑科技之relay log大法
Preface In my previous blogs,I've demonstrated several mothods of how to rescue a dropped ta ...
- linux系统下怎么关闭一个端口
netstat -an | grep 22查看22端口 netstat -ntulp |grep 80 //查看所有80端口使用情况
- 孤荷凌寒自学python第四十八天通用同一数据库中复制数据表函数最终完成
孤荷凌寒自学python第四十八天通用同一数据库中复制数据表函数最终完成 (完整学习过程屏幕记录视频地址在文末) 今天继续建构自感觉用起来顺手些的自定义模块和类的代码. 今天经过反复折腾,最终基本上算 ...
- CodeBlocks X64 SVN 编译版
CodeBlocks X64 SVN 编译版 采用官方最新的SVN源码编译而来,纯64位的,所以32位系统是不能使用的.字体使用的是微软的YaHei UI字体,如果有更好的字节建议,可以留言. 由于直 ...
- 上手Caffe(二)
@author:oneBite本文简述如何在windows环境下,运行caffe的“hello world”例程体会适用caffe的流程:转换输入数据格式>在solver.prototxt中配置 ...
- ZOJ 3606 Lazy Salesgirl ( 线段树 + 思路 )
卖切糕的小女孩 http://www.cnblogs.com/wuyiqi/archive/2012/04/28/2474672.html #include <cstdio> #inclu ...
- JSP/Servlet Web 学习笔记 DayOne
JSP概述 1)JSP是一种动态网页技术标准,它是在传统的页面HTML文件中插入Java程序段和JSP标记(tag),从而形成JSP文件(*.jsp),也称JSP页面. 2)JSP容器是一个支持JSP ...
- Android记事本06
昨天: activity的生命周期 今天: activity横竖屏切换的生命周期 遇到的问题: 为了匹配ADK,下载了更旧的版本SDK,布局文件仍然无法显示.