數據結構與算法(23)——表達式解析


  • 樹的應用:表達式解析

 

 

解析全括號表達式:(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 ) )')

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM