資料結構:Expression Tree
Expression Tree即表示式樹,專門用於計算表示式。例如,3-(4+5),轉化成list形式,即['3','-','(','4','+','5',')'],其表示式樹為:
-
/
3 +
/
4 5
這樣安排的好處是,這棵樹的後續遍歷就是逆波蘭表示式,即[3,4,5,+,-]。由逆波蘭表示式即可進行計算。
表示式樹的關鍵在於生成,生成是根據優先度來決定的。對於普通的加減乘除表示式,有以下規定:
- 數字的優先度是最大的;
- +-優先度為+1
- */優先度為+2
- 遇到'(',優先度+10;遇到')',優先度減10
則例子中的優先度list是[max, 1, max, 11, max]。把括號從計算當中去除。
那麼,相當於把表示式轉換成為了一個最小樹,優先度最小的在上面,優先度最大的數字在葉子節點上。
而對於生成最大/最小樹,有一個很優雅的解法: - 新建一個stk,然後對優先度list遍歷;
- 對於一個元素n,每當stk之前的元素比其大,就將其作為n的左子樹,直至stk為空,或者遇到一個比n小的元素,此時就把n作為其右子樹;
- 直至遍歷結束,返回stk[0]即可。
要實現“一條龍服務”,需要以下功能: - 從字串表示式到表示式的list形式;T:O(n) S:O(n)
- 從表示式list到表示式樹;T:O(n) S:O(n)
- 對錶達式樹後序遍歷獲得逆波蘭表示式;T:O(n) S:O(n)
- 對逆波蘭表示式進行計算。T:O(n) S:O(n)
總體複雜度T:O(n) S:O(n)。雖然有點長,但是解決了不少表示式計算的問題。程式碼如下:
class MyTreeNode:
def __init__(self, val, s):
self.left = None
self.right = None
self.val = val
self.s = s
maxint = 0x7fffffff
class ExpressionTree:
# convert the str expression to the list form
def convert(self, s):
if not s:
return []
ret = []
i = 0
while i < len(s):
if s[i] in ['+','-','*','/','(',')']:
ret.append(s[i])
i += 1
else:
j = i
while j < len(s) and s[j] not in ['+','-','*','/','(',')']:
j += 1
ret.append(s[i:j])
i = j
return ret
# build theexpression tree using the expression list
def build(self, expression):
# writeyour code here
return self.create_tree(expression)
# calculate theexpression value using the expression tree
def calculate(self, node):
exp = []
self.postOrder(node, exp)
operands, operators= [], []
for i in range(len(exp)):
if exp[i] in ['+', '-', '*', '/']:
operators.append(exp[i])
self.compute(operands, operators)
else:
operands.append(float(exp[i]))
return operands[0] if len(operands) > 0 else 0
def compute(self, operands, operators):
right, left = operands.pop(), operands.pop()
op = operators.pop()
if op == '+':
operands.append(left + right)
elif op == '-':
operands.append(left - right)
elif op == '*':
operands.append(left * right)
elif op == '/':
operands.append(left / right)
def get_val(self, a, base):
if a == '+' or a == '-':
if base == maxint:
return base
return 1 + base
if a == '*' or a == '/':
if base == maxint:
return base
return 2 + base
return maxint
def create_tree(self, expression):
stack = []
base = 0
for i in range(len(expression)):
if expression[i] == '(':
if base != maxint:
base += 10
continue
elif expression[i]== ')':
if base != maxint:
base -= 10
continue
val = self.get_val(expression[i], base)
node = MyTreeNode(val, expression[i])
while stack and val <= stack[-1].val:
node.left = stack.pop()
if stack:
stack[-1].right = node
stack.append(node)
if not stack:
return None
return stack[0]
def postOrder(self, node, exp):
if not node:
return
self.postOrder(node.left, exp)
self.postOrder(node.right, exp)
exp.append(node.s)
def oneStepCalculate(self, s):
if not s:
return 0
exp = self.convert(s)
n = self.build(exp)
return self.calculate(n)
if __name__ == "__main__":
print(ExpressionTree().oneStepCalculate("3/5+1.4*6"))
print(ExpressionTree().oneStepCalculate("1+(2*(4-6))"))
print(ExpressionTree().oneStepCalculate("5/(2+(3*(4/3)))"))
print(ExpressionTree().oneStepCalculate("1/(2+3)+(5+(6-8))"))
print(ExpressionTree().oneStepCalculate("1"))
print(ExpressionTree().oneStepCalculate("1+1"))
相關文章
- 資料結構-Tree資料結構
- 『資料結構』樹(Tree)資料結構
- js資料結構--樹(tree)JS資料結構
- 【資料結構】K-D Tree資料結構
- 詳解資料庫儲存的資料結構LSM Tree資料庫資料結構
- 資料的儲存結構淺析LSM-Tree和B-tree
- 資料結構分析及其實現(Stack、Queue、Tree、LinkedList)資料結構
- 區塊鏈中的資料結構之 Merkle Tree區塊鏈資料結構
- B-tree和B+tree 一種為資料查詢而生的結構
- 每週一練 之 資料結構與演算法(Tree)資料結構演算法
- 前端樹形Tree資料結構使用-🤸🏻♂️各種姿勢總結前端資料結構
- [譯文] 初學者應該瞭解的資料結構: Tree資料結構
- 結構化資料、半結構化資料和非結構化資料
- 【資料結構篇】認識資料結構資料結構
- 資料結構小白系列之資料結構概述資料結構
- LayUI—tree樹形結構的使用UI
- 資料結構資料結構
- 資料結構與演算法-資料結構(棧)資料結構演算法
- 【PHP資料結構】PHP資料結構及演算法總結PHP資料結構演算法
- leetcode演算法資料結構題解---資料結構LeetCode演算法資料結構
- 資料結構——樹資料結構
- Redis資料結構Redis資料結構
- 資料結構-樹資料結構
- Python資料結構Python資料結構
- 資料結構-堆資料結構
- 資料結構-集合資料結構
- 資料結構 - 字串資料結構字串
- 資料結構---串資料結構
- 資料結構-棧資料結構
- Map 資料結構資料結構
- 【模板】資料結構資料結構
- 模板 - 資料結構資料結構
- 14 資料結構資料結構
- 資料結構 - 堆資料結構
- [資料結構]堆資料結構
- 資料結構 - 圖資料結構
- 資料結構 - 棧資料結構
- 資料結構——列表資料結構
- Redis 資料結構Redis資料結構