- 樹的應用:表達式解析
解析全括號表達式:(3+(4*5))
- 創建過程:
創建空樹,當前節點為根節點
讀入'(',創建了左子節點,當前節點下降
讀入'3',當前節點設置為3,上升到父節點
讀入'+',當前節點設置為+,創建右子節點,當前節點下降。
讀入'(',創建左子節點,當前節點下降
讀入'4',當前節點設置為4,上升到父節點
讀入'*',當前節點設置為*,創建右子節點,當 前節點下降
讀入'5',當前節點設置為5,上升到父節點
讀入')',上升到父節點
讀入')',再上升到父節點
總結下:如果當前單詞是"(":為當前節點添加一個新節 點作為其左子節點,當前節點下降為這個新節點 如果當前單詞是操作符"+,-,/,*":將當前節點 的值設為此符號,為當前節點添加一個新節點作 為其右子節點,當前節點下降為這個新節點 如果當前單詞是操作數:將當前節點的值設為此 數,當前節點上升到父節點 如果當前單詞是")":則當前節點上升到父節點。
創建左右子樹可調用insertLeft/Right
當前節點設置值,可以調用setRootVal
下降到左右子樹可調用getLeft/RightChild
創建一個棧來跟蹤父節點:當前節點下降時,將下降前的節點push入棧 當前節點需要上升到父節點時,上升到pop出棧的節點即可!
from Stack import Stack from Binary_Tree import BinaryTree 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)) #設置當前節點的值,為操作數 parent = pStack.pop() #出棧上升 currentTree = parent #上升 elif i in ['+', '-', '*', '/']: currentTree.setRootVal(i) #將當前階段設置成操作符 currentTree.insertRight('') #創建右子樹 pStack.push(currentTree) #把老的當前節點push到棧中 currentTree = currentTree.getRightChild() elif i == ")": currentTree = pStack.pop() else: raise ValueError return eTree flist = buildParseTree('( 3 + ( 4 * 5 ) )')
- 利用表達式解析樹求值
創建了表達式解析樹,可用來進行求值。由於二叉樹BinaryTree是一個遞歸數據 結構,自然可以用遞歸算法來處理。由前述對子表達式的描述,可從樹的底層子樹開 始,逐步向上層求值,最終得到整個表達式的值。
求值函數evaluate的遞歸三要素:
基本結束條件:葉節點是最簡單的子樹,沒有左 右子節點,其根節點的數據項即為子表達式樹的值
縮小規模:將表達式樹分為左子樹、右子樹,即為縮小規模
調用自身:分別調用evaluate計算左子樹和右 子樹的值,然后將左右子樹的值依根節點的操作 符進行計算,從而得到表達式的值
這里引用函數引用包 operator。
from Stack import Stack from Binary_Tree import BinaryTree 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)) #設置當前節點的值,為操作數 parent = pStack.pop() #出棧上升 currentTree = parent #上升 elif i in ['+', '-', '*', '/']: currentTree.setRootVal(i) #將當前階段設置成操作符 currentTree.insertRight('') #創建右子樹 pStack.push(currentTree) #把老的當前節點push到棧中 currentTree = currentTree.getRightChild() elif i == ")": currentTree = pStack.pop() else: raise ValueError return eTree flist = buildParseTree('( 3 + ( 4 * 5 ) )')