目录
一、建立表达式解析树:实例
全括号表达式:(3+(4*5))
二、利用表达式解析树求值:思路
从图示过程我们可以看到,创建树过程中关键的是对当前节点的跟踪:
-
创建左右子树可调用insertLeft/Right
-
当前节点设置值,可以调用setRootVal
-
下降到左右子树可以调用getLeft/RightChid
-
但是,上升到父节点,这个没有方法支持。
我们可以用一个栈来记录跟踪父节点:
-
当前节点需要下降时,将下降的节点push入栈
-
当前节点需要上升到父节点时,上升到pop出栈的节点即可
建立表达式解析树代码:
def buildParseTree(fpexp):
fplist = fpexp.split()
pStack = Stack() # 创建空栈
eTree = Binarytree('') # 创建二叉树
pStack.push(eTree) # 入栈下降
currentTree = eTree
for i in fplist:
if i == '(': # 表达式开始
currentTree.insertLeft('')
pStack.push(currentTree) # 入栈下降
currentTree = currentTree.getLeftChild()
elif i not in ['+', '-', '*', '/', ')']: # 操作数
currentTree.setRootVal(int(i))
parnt = pStack.pop() # 出栈上升
currentTree = parnt
elif i in ['+', '-', '*', '/']: # 操作符
currentTree.setRootVal(i)
currentTree.insertLeft('')
pStack.push(currentTree)
currentTree = currentTree.getRightChild()
elif i == ')': # 表达式结束
currentTree = pStack.pop() # 出栈上升
else:
raise ValueError
return 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:
parsetree.getRootVal()