前序、中序和后序表达式转换问题
前序、中序、后序表达式举例:
从这个表格中可以看到中序表达式和前序表达式、后序表达式的区别,中序表达式有括号,前序和后序没有括号。
那么为什么前序表达式和后序表达式不需要括号?答案是,这两种表达式中的运算符所对应的操作数是明确的。只有中序表达式需要额外的符号来消除歧义。前序表达式和后序表达式的运算顺序完全由运算符的位置决定。
以A + B * C为例,操作数 A 、B 和 C 的相对位置保持不变,只有运算符改变了位置。再观察中序表达式中的运算符。从左往右看,第一个出现的运算符是 + 。但是在后序表达式中,由于 * 的优先级更高(写成完全括号表达式后乘法所在的括号先进行运算),因此 * 先于 + 出现,前序表达式与后序表达式相反。
将中序表达式转换为后序表达式的步骤如下:
(1) 创建用于保存运算符的空栈,以及一个用于保存结果的空列表。
(2) 从左往右扫描这个标记列表。
- 如果标记是操作数,将其添加到结果列表的末尾。
- 如果标记是左括号,将其压入栈中。
- 如果标记是右括号,反复从栈中移除元素,直到移除对应的左括号。将从栈中
- 取出的每一个运算符都添加到结果列表的末尾。
- 如果标记是运算符,将其压入栈中。但是,在这之前,需要先从栈中取出优先
- 级更高或相同的运算符,并将它们添加到结果列表的末尾。
(3) 当处理完输入表达式以后,检查栈中是否有多余的运算符。将其中所有残留的运算符全部添加到结果列表的末尾。
以A*B+C*D为例,转换后表达式为AB*CD*+:
中序表达式转换后序表达式代码如下:
首先创建栈的结构
class Stack(object):def __init__(self):self.__items = []def isEmpty(self):"""检查栈是否为空"""return self.__items == []def push(self, item):"""将一个元素添加到栈的顶端"""self.__items.append(item)def pop(self):"""将栈顶端的元素移除"""return self.__items.pop()def peek(self):"""返回栈顶端的元素"""return self.__items[len(self.__items) - 1]def size(self):"""返回栈中元素的数目"""return len(self.__items)
转换表达式
import stack
import stringdef toPostfix(symbolString):"""中序表达式转后序表达式"""# 设定操作符优先级,保证乘除优先级大于加减大于括号即可# 不需要设‘)’的优先级,因为不会使用到prec = {}prec['/'] = 3prec['*'] = 3prec['+'] = 2prec['-'] = 2prec['('] = 1s = stack.Stack()str_list = []for token in symbolString:if token in string.ascii_uppercase:str_list.append(token)elif token == '(':s.push(token)elif token == ')': # 找到前一个“(”匹配peek = s.pop()# 如果是操作符就直接把操作符移入列表中while peek != '(':str_list.append(peek)peek = s.pop()else:# 保证进入列表的优先级比栈中操作符的优先级要低while (not s.isEmpty()) and prec[token] <= prec[s.peek()]:str_list.append(peek)s.push(token)# 将剩余的栈中的操作符加入到列表中while not s.isEmpty():str_list.append(s.pop())return ''.join(str_list)
中序转前序表达式原理同后序是一样的,只不过在后序的基础上进行了字符串的反转
中序表达式转前序表达式步骤如下:
(1)反转输入字符串,如“(A+B)*(C+D)” 反转后为“(D+C)*(B+A)”。
(2)从字符串中取出下一个字符。
- 如果是操作数,则直接输出。
- 如果是“)”,压入栈中。
- 如果是运算符但不是“(”,“)”,则不断循环进行以下处理:如果栈为空,则此运算符进栈,结束此步骤;如果栈顶是“)”,则此运算符进栈,结束此步骤;如果此运算符与栈顶优先级相同或者更高,此运算符进栈,结束此步骤;否则,运算符连续出栈,直到满足上述三个条件之一,然后此运算符进栈。
- 如果是“(”,则运算符连续出栈,直到遇见“)”为止,将“)”出栈且丢弃之。
- 如果还有更多的字符串,则转到第2步。
- 如果不再有未处理的字符串了,输出栈中剩余元素。
(3)再次反转字符串得到最终结果。
中序表达式转换前序表达式代码如下:
def toPrefix(symbolString):"""中序表达式转前序表达式"""prec = {}prec['/'] = 3prec['*'] = 3prec['+'] = 2prec['-'] = 2prec[')'] = 1s = stack.Stack()str_list = []symbolString = symbolString[::-1] # 反转表达式for token in symbolString:if token in string.ascii_uppercase:str_list.append(token)elif token == ')':s.push(token)elif token == '(': # 找到前一个“)”匹配peek = s.pop()# 如果是操作符就直接把操作符移入列表中while peek != ')':str_list.append(peek)peek = s.pop()else:# 保证进入列表的优先级比栈中操作符的优先级要低while (not s.isEmpty()) and prec[token] < prec[s.peek()]:str_list.append(s.pop())s.push(token)# 将剩余的栈中的操作符加入到列表中while not s.isEmpty():str_list.append(s.pop())return ''.join(str_list[::-1])
前序、中序和后序表达式转换问题相关推荐
- 前序、中序、后序表达式
前序.中序.后序表达式的差异主要在于运算符所在位置不同,前序表达式是将运算符卸载两个操作数之前,例如: 前序:+XY 中序:X+Y 后序:XY+ 通常中序表达式是我们最熟悉的,如中序表达式:X+Y*Z ...
- java二叉树合并_Java(树的前中后序遍历构造二叉树题型整合)前序和中序、中序和后序、前序和后序遍历序列构造二叉树算法整合归纳...
前言 二叉树各种花里胡哨的算法题真的把我搞晕了,今天特地整理出一类有关二叉树的算法题,希望能帮助阅读到此文章的人,今后不再受此类题型的困扰. 一.题目类型 已知二叉树的两种遍历序列,请根据该序列构建二 ...
- 二叉树深度优先 java_二叉树遍历(前序、中序、后序、层次、深度优先、广度优先遍历) java实现...
二叉树是一种非常重要的数据结构,非常多其他数据结构都是基于二叉树的基础演变而来的.对于二叉树,有深度遍历和广度遍历,深度遍历有前序.中序以及后序三种遍历方法,广度遍历即我们寻常所说的层次遍历.由于树的 ...
- 手动创建一棵二叉树,然后利用前序、中序、后序、层序进行遍历(从创建二叉树到各种方式遍历)(含运行结果)
手动创建一棵二叉树,然后利用前序.中序.后序.层序进行遍历 import java.util.LinkedList; import java.util.List; import java.util.Q ...
- 把一个数组的值存入二叉树中,然后利用前序、中序、后序3种方式进行遍历(完整代码以及运行结果)(Java)
把一个数组的值存入二叉树中,然后利用前序.中序.后序3种方式进行遍历(完整代码以及运行结果) 在最近的面试过程中,听说有小伙伴被面试官要求创建二叉树,然后对该二叉树进行遍历,感觉这一直以来都是一个大家 ...
- 【LeetCode系列】从中序与后序遍历序列构造二叉树 从前序与中序遍历序列构造二叉树...
关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 105. 从前序与中序遍历序列构造二叉树 根据一棵树的前序遍历与中序遍历构造二叉树 ...
- 105从前序与中序遍历序列构造二叉树 106 从中序与后序遍历序列构造二叉树 (递归 + 哈希)
引言 这两道题主要是考察二叉树遍历的掌握,即由前序和中序推出原二叉树,由后序和中序推出原二叉树,这里先来说一下推导过程: 前序和中序 知道前序遍历和中序遍历,如何推原二叉树?(直接是结论,可以自行推导 ...
- 二叉树前序、中序、后序遍历求法
二叉树前序.中序.后序遍历相互求法 二叉树的三种遍历方法: 前序遍历: 1.访问根节点 2.前序遍历左子树 3.前序遍历右子树 中序遍历: 1.中序遍历左子树 2.访问根节点 3.中序遍历右子树 后序 ...
- PHP实现二叉树的深度优先遍历(前序、中序、后序)和广度优先遍历(层次) 转载陈小龙哈2017...
http://blog.csdn.net/baidu_30000217/article/details/52953127 前言: 深度优先遍历:对每一个可能的分支路径深入到不能再深入为止,而且每个结点 ...
最新文章
- 拜托,面试别再问我时间复杂度了!!!
- 人机语言(MML: Man-Machine Language)
- 通俗易懂,带你了解Kafka
- 【Centos 7】【Docker】 安装 kafka
- 使用AWS Lambda在Go中构建RESTful API
- 前端学习(1773):前端调试之快速清空所有的本地存储资源
- 元旦限时特惠,耳机、书籍等大降价
- 适用于各种列表操作的Python程序
- 使用Chrome保存网页为mht文件
- MVC与三层架构讲解
- 僵尸 AI 来了,人类该怎么办?
- mysql断言命令_mysql的触发模拟断言
- 谷歌浏览器的笔记在哪里_selenium学习笔记之启动谷歌浏览器
- CCNA(高级实验)
- html网页版国际象棋,棋友推荐的十五大国外国际象棋网站
- 【微信公众号-订阅号发送群发消息】
- ADNI静息态功能核磁共振成像数据预处理总流程
- 如何下载3GPP协议
- [feather]StarlingUi框架——初识feather、界面启动及Ui加载
- 爬虫实战:链家租房数据爬取,实习僧网站数据爬取
热门文章
- epoll---Rector模型
- 【电商】管理后台篇--库存管理(货位、调拨、盘点)
- 从0基础开始学软件测试进阶自动化最全路线图【乐搏TestPRO】
- html中数组的定义,javascript中数组定义的几种方式是什么?
- 架构的本质是管理复杂性,微服务本身也是架构演化的结果
- Error: Unable to access jarfile /www/wwwroot/xxxx.jar--server.port=5635 问题解决
- 浏览器滑块、鼠标事件、鼠标滑轮、键盘事件详细说明
- 01基础 4、Shell 脚本
- Pygame飞机大战一个简单的双人模式测试
- day1 机器学习基础