前序、中序、后序表达式举例:

从这个表格中可以看到中序表达式和前序表达式、后序表达式的区别,中序表达式有括号,前序和后序没有括号。

那么为什么前序表达式和后序表达式不需要括号?答案是,这两种表达式中的运算符所对应的操作数是明确的。只有中序表达式需要额外的符号来消除歧义。前序表达式和后序表达式的运算顺序完全由运算符的位置决定。​

以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])

前序、中序和后序表达式转换问题相关推荐

  1. 前序、中序、后序表达式

    前序.中序.后序表达式的差异主要在于运算符所在位置不同,前序表达式是将运算符卸载两个操作数之前,例如: 前序:+XY 中序:X+Y 后序:XY+ 通常中序表达式是我们最熟悉的,如中序表达式:X+Y*Z ...

  2. java二叉树合并_Java(树的前中后序遍历构造二叉树题型整合)前序和中序、中序和后序、前序和后序遍历序列构造二叉树算法整合归纳...

    前言 二叉树各种花里胡哨的算法题真的把我搞晕了,今天特地整理出一类有关二叉树的算法题,希望能帮助阅读到此文章的人,今后不再受此类题型的困扰. 一.题目类型 已知二叉树的两种遍历序列,请根据该序列构建二 ...

  3. 二叉树深度优先 java_二叉树遍历(前序、中序、后序、层次、深度优先、广度优先遍历) java实现...

    二叉树是一种非常重要的数据结构,非常多其他数据结构都是基于二叉树的基础演变而来的.对于二叉树,有深度遍历和广度遍历,深度遍历有前序.中序以及后序三种遍历方法,广度遍历即我们寻常所说的层次遍历.由于树的 ...

  4. 手动创建一棵二叉树,然后利用前序、中序、后序、层序进行遍历(从创建二叉树到各种方式遍历)(含运行结果)

    手动创建一棵二叉树,然后利用前序.中序.后序.层序进行遍历 import java.util.LinkedList; import java.util.List; import java.util.Q ...

  5. 把一个数组的值存入二叉树中,然后利用前序、中序、后序3种方式进行遍历(完整代码以及运行结果)(Java)

    把一个数组的值存入二叉树中,然后利用前序.中序.后序3种方式进行遍历(完整代码以及运行结果) 在最近的面试过程中,听说有小伙伴被面试官要求创建二叉树,然后对该二叉树进行遍历,感觉这一直以来都是一个大家 ...

  6. 【LeetCode系列】从中序与后序遍历序列构造二叉树 从前序与中序遍历序列构造二叉树...

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 105. 从前序与中序遍历序列构造二叉树 根据一棵树的前序遍历与中序遍历构造二叉树 ...

  7. 105从前序与中序遍历序列构造二叉树 106 从中序与后序遍历序列构造二叉树 (递归 + 哈希)

    引言 这两道题主要是考察二叉树遍历的掌握,即由前序和中序推出原二叉树,由后序和中序推出原二叉树,这里先来说一下推导过程: 前序和中序 知道前序遍历和中序遍历,如何推原二叉树?(直接是结论,可以自行推导 ...

  8. 二叉树前序、中序、后序遍历求法

    二叉树前序.中序.后序遍历相互求法 二叉树的三种遍历方法: 前序遍历: 1.访问根节点 2.前序遍历左子树 3.前序遍历右子树 中序遍历: 1.中序遍历左子树 2.访问根节点 3.中序遍历右子树 后序 ...

  9. PHP实现二叉树的深度优先遍历(前序、中序、后序)和广度优先遍历(层次) 转载陈小龙哈2017...

    http://blog.csdn.net/baidu_30000217/article/details/52953127 前言: 深度优先遍历:对每一个可能的分支路径深入到不能再深入为止,而且每个结点 ...

最新文章

  1. 拜托,面试别再问我时间复杂度了!!!
  2. 人机语言(MML: Man-Machine Language)
  3. 通俗易懂,带你了解Kafka
  4. 【Centos 7】【Docker】 安装 kafka
  5. 使用AWS Lambda在Go中构建RESTful API
  6. 前端学习(1773):前端调试之快速清空所有的本地存储资源
  7. 元旦限时特惠,耳机、书籍等大降价
  8. 适用于各种列表操作的Python程序
  9. 使用Chrome保存网页为mht文件
  10. MVC与三层架构讲解
  11. 僵尸 AI 来了,人类该怎么办?
  12. mysql断言命令_mysql的触发模拟断言
  13. 谷歌浏览器的笔记在哪里_selenium学习笔记之启动谷歌浏览器
  14. CCNA(高级实验)
  15. html网页版国际象棋,棋友推荐的十五大国外国际象棋网站
  16. 【微信公众号-订阅号发送群发消息】
  17. ADNI静息态功能核磁共振成像数据预处理总流程
  18. 如何下载3GPP协议
  19. [feather]StarlingUi框架——初识feather、界面启动及Ui加载
  20. 爬虫实战:链家租房数据爬取,实习僧网站数据爬取

热门文章

  1. epoll---Rector模型
  2. 【电商】管理后台篇--库存管理(货位、调拨、盘点)
  3. 从0基础开始学软件测试进阶自动化最全路线图【乐搏TestPRO】
  4. html中数组的定义,javascript中数组定义的几种方式是什么?
  5. 架构的本质是管理复杂性,微服务本身也是架构演化的结果
  6. Error: Unable to access jarfile /www/wwwroot/xxxx.jar--server.port=5635 问题解决
  7. 浏览器滑块、鼠标事件、鼠标滑轮、键盘事件详细说明
  8. 01基础 4、Shell 脚本
  9. Pygame飞机大战一个简单的双人模式测试
  10. day1 机器学习基础