数据结构与算法(Python版)四十八:树的应用(表达式解析)
树的应用:解析树(语法树)
将树用于表示语言中句子, 可以分析句子的各种语法成分, 对句子的各种成分进行处理
语法分析树主谓宾,定状补
程序设计语言的编译
词法、语法检查从语法树生成目标代码
自然语言处理
机器翻译、语义理解
树的应用: 表达式解析
我们还可以将表达式表示为树结构
叶节点保存操作数,内部节点保存操作符
全括号表达式((7+3)*(5-2))
由于括号的存在,需要计算*的话,就必须先计算7+3和5-2,表达式层次决定计算的优先级越底层的表达式,优先级越高
树中每个子树都表示一个子表达式
将子树替换为子表达式值的节点,即可实现求值
表达式解析树
下面, 我们用树结构来做如下尝试
从全括号表达式构建表达式解析树,利用表达式解析树对表达式求值,从表达式解析树恢复原表达式的字符串形式
首先, 全括号表达式要分解为单词Token列表
其单词分为括号“() ”、操作符“±*/”和操作数“0~9”这几类,左括号就是表达式的开始,而右括号是表达式的结束
建立表达式解析树:实例
全括号表达式: (3+(4*5))
创建表达式解析树过程
- 创建空树,当前节点为根节点
- 读入’(’, 创建了左子节点,当前节点下降
- 读入’3’,当前节点设置为3, 上升到父节点
- 读入’+’,当前节点设置为+, 创建右子节点,当前节点下降
- 读入’(’, 创建左子节点,当前节点下降
- 读入’4’,当前节点设置为4, 上升到父节点
- 读入’’,当前节点设置为, 创建右子节点,当前节点下降
![]() |
![]() |
![]() |
- 读入’5’,当前节点设置为5, 上升到父节点
- 读入’)’, 上升到父节点
- 读入’)’,再上升到父节点
建立表达式解析树:规则
从左到右扫描全括号表达式的每个单词,依据规则建立解析树
如果当前单词是"(":为当前节点添加一个新节点作为其左子节点, 当前节点下降为这个新节点。如果当前单词是操符"+,-,/,*":将当前节点的值设为此符号,为当前节点添加一个新节点作为其右子节点, 当前节点下降为这个新节点,如果当前单词是操作数:将当前节点的值设为此数, 当前节点上升到父节点,如果当前单词是")":则当前节点上升到父节点
建立表达式解析树:实例
全括号表达式: (3+(4*5))
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
建立表达式解析树:思路
从图示过程中我们看到, 创建树过程中关键的是对当前节点的跟踪
- 创建左右子树可调用insertLeft/Right
- 当前节点设置值,可以调用setRootVal
- 下降到左右子树可调用getLeft/RightChild
- 但是, 上升到父节点,这个没有方法支持!
我们可以用一个栈来记录跟踪父节点
- 当前节点下降时,将下降前的节点push入栈
- 当前节点需要上升到父节点时,上升到pop出栈的节点即可!
建立表达式解析树:代码
class BinaryTree:def __init__(self, rootObj):self.key = rootObjself.leftChild = Noneself.rightChild = Nonedef insertLeft(self, newNode):if self.leftChild == None:self.leftChild = BinaryTree(newNode)else:t = BinaryTree(newNode)t.leftChild = self.leftChildself.leftChild = tdef insertRight(self, newNode):if self.rightChild == None:self.rightChild = BinaryTree(newNode)else:t = BinaryTree(newNode)t.rightChild = self.rightChildself.rightChild = tdef getRightChild(self):return self.rightChilddef getLeftChild(self):return self.leftChilddef setRootVal(self, obj):self.key = objdef getRootVal(self):return self.keyclass Stack: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[-1]def size(self):return len(self.items)def buildParseTree(fpexp):fplist = fpexp.split()pStack = Stack()eTree = BinaryTree('')# 入栈下降pStack.push(eTree)currentTree = eTreefor i in fplist:# 表达式开始if i == '(':currentTree.insertLeft('')# 入栈下降pStack.push(currentTree)currentTree = currentTree.getLeftChild()# 操作数elif i not in ['+', '-', '*', '/', ')']:currentTree.setRootVal(int(i))# 出栈上升parent = pStack.pop()currentTree = parent# 操作符elif i in ['+', '-', '*', '/']:currentTree.setRootVal(i)currentTree.insertRight('')pStack.push(currentTree)currentTree = currentTree.getRightChild()# 表达式结束elif i == ')':# 出栈上升currentTree = pStack.pop()else:raise ValueErrorreturn eTree
创建了表达式解析树, 可用来进行求值
由于二叉树BinaryTree是一个递归数据结构, 自然可以用递归算法来处理
求值递归函数evaluate
由前述对子表达式的描述,可从树的底层子树开始,逐步向上层求值,最终得到整个表达式的值
求值函数evaluate的递归三要素:
- 基本结束条件:叶节点是最简单的子树,没有左右子节点,其根节点的数据项即为子表达式树的值
- 缩小规模:将表达式树分为左子树、右子树,即为缩小规模
- 调用自身:分别调用evaluate计算左子树和右子树的值,然后将左右子树的值依根节点的操作符进行计算,从而得到表达式的值
一个增加程序可读性的技巧:函数引用
利用表达式解析树求值:代码
import operator
def evaluate(parseTree):opers = {'+': operator.add, '-': operator.sub, '*': operator.mul, '/': operator.truediv}# 缩小规模leftC = parseTree.getLeftChild()rightC = parseTree.getRightChild()if leftC and rightC:fn = opers[parseTree.getRootVal()]# 递归调用return fn(evaluate(leftC), evaluate(rightC))else:# 基本结束条件return parseTree.getRootVal()
数据结构与算法(Python版)四十八:树的应用(表达式解析)相关推荐
- 数据结构与算法(Python版)二十二:递归可视化(谢尔宾斯基三角形)
谢尔宾斯基Sierpinski三角形 分形构造, 平面称谢尔宾斯基三角形, 立体称谢尔宾斯基金字塔 谢尔宾斯基三角形:作图思路 根据自相似特性, 谢尔宾斯基三角形是由3个尺寸减半的谢尔宾斯基三角形按照 ...
- mooc数据结构与算法python版第十周作业_中国大学mooc慕课_数据结构与算法Python版_章节答案...
新入对于接诊人的院病与查房,中国章节在多必须经治间内进行医师长时. 大学答案高的主要文库日常利用率较有(. 须注下问题:慕课意以,者以知识作为的投资产权出资.在配置上电装,该装装在置(线应部位)的接地 ...
- mooc数据结构与算法python版期末考试_数据结构与算法Python版-中国大学mooc-试题题目及答案...
数据结构与算法Python版-中国大学mooc-试题题目及答案 更多相关问题 婴儿出生一两天后就有笑的反应,这种笑的反应属于(). [判断题]填制原始凭证,汉字大写金额数字一律用正楷或草书书写,汉字大 ...
- python数据结构算法 北京大学_北京大学公开课《数据结构与算法Python版》
之前我分享过一个数据结构与算法的课程,很多小伙伴私信我问有没有Python版. 看了一些公开课后,今天特向大家推荐北京大学的这门课程:<数据结构与算法Python版>. 课程概述 很多同学 ...
- 数据结构与算法 python版 之 递归三定律
#数据结构与算法 python版 之 谢尔宾斯基三角形 , 树叉 1.为了向阿西莫夫的"机器人三定律"直径,递归算法也总结出"三定律" 1递归算法必须有一个基本 ...
- 数据结构python版 答案,中国大学 MOOC_数据结构与算法Python版_章节测验答案
中国大学 MOOC_数据结构与算法Python版_章节测验答案 更多相关问题 认识的本质是()A.肯定世界是可知的B.主体对客体的能动反映C.主体对客体的直观反映D.实践是 水灰比是影响混凝土()的主 ...
- 数据结构与算法python版 MOOC 第九周
九.树及算法-上 本系列博客基于" (北京大学)数据结构与算法python版"慕课,课程在中国大学慕课和bilibili上均可找到. 1. 内容 树结构的相关术语 树的表示方法:嵌 ...
- mooc数据结构与算法python版期末测验_中国大学数据结构与算法Python版答案_MOOC慕课章节期末答案...
中国大学数据结构与算法Python版答案_MOOC慕课章节期末答案 更多相关问题 java.lang 包的 Character 类的 isJavaIdentifierStart 方法的功能是用来判断某 ...
- mooc数据结构与算法python版第十一周作业_中国大学 MOOC_数据结构与算法Python版_2020最新答案学习指南...
中国大学 MOOC_数据结构与算法Python版_2020最新答案学习指南 更多相关问题 [判断题]实际集成运放的上限截止频率为无穷大 [多选题]现代城市的发展凸现出与以往不同的动力机制包括 教师在引 ...
最新文章
- python urllib.request 爬虫 数据处理-Python爬虫学习之(二)| urllib进阶篇
- 黄聪:C#代码生成工具:文本模板初体验 Hello,World!
- DBA查询命令积累——不断更新
- 【Redis】1.Redis入门简介以及基本操作命令
- (转)java动态代理与aop
- sql/c#十六进制与十进制的转换
- apipost 如何分享多个接口
- linux设置ipsan_linux 配置SAN存储-IPSAN
- 虚拟机Ubuntut tftp服务不启动,service tftpd-hpa restart 失败的处理
- win10总显示打印机未连接服务器,win10系统打印机共享提示连接失败的解决方法...
- The working copy needs to be upgraded
- 计算机酷睿处理器排行,2018电脑英特尔处理器排名(cpu性能天梯图)
- 一招学会绘制UI图标超椭圆
- 亲手打造自己的 Linux 桌面环境
- matlab状态空间模型构建函数ss
- 鲲鹏生态跑出加速度 中原数字经济再续新动能
- 2018十大最热门编程语言排行榜出炉,Java竟不是第一!
- 关于ffmpeg如何下载、安装和使用
- 如何利用计算机班级成绩分析,北京自考计算机应用基础课成绩分析报告
- 骑行318、 2016.7.30