数据结构:Expression Tree

Expression Tree即表达式树,专门用于计算表达式。例如,3-(4+5),转化成list形式,即['3','-','(','4','+','5',')'],其表达式树为:
-
/
3 +
/
4 5
这样安排的好处是,这棵树的后续遍历就是逆波兰表达式,即[3,4,5,+,-]。由逆波兰表达式即可进行计算。
表达式树的关键在于生成,生成是根据优先度来决定的。对于普通的加减乘除表达式,有以下规定:

  1. 数字的优先度是最大的;
  2. +-优先度为+1
  3. */优先度为+2
  4. 遇到'(',优先度+10;遇到')',优先度减10
    则例子中的优先度list是[max, 1, max, 11, max]。把括号从计算当中去除。
    那么,相当于把表达式转换成为了一个最小树,优先度最小的在上面,优先度最大的数字在叶子节点上。
    而对于生成最大/最小树,有一个很优雅的解法:
  5. 新建一个stk,然后对优先度list遍历;
  6. 对于一个元素n,每当stk之前的元素比其大,就将其作为n的左子树,直至stk为空,或者遇到一个比n小的元素,此时就把n作为其右子树;
  7. 直至遍历结束,返回stk[0]即可。
    要实现“一条龙服务”,需要以下功能:
  8. 从字符串表达式到表达式的list形式;T:O(n) S:O(n)
  9. 从表达式list到表达式树;T:O(n) S:O(n)
  10. 对表达式树后序遍历获得逆波兰表达式;T:O(n) S:O(n)
  11. 对逆波兰表达式进行计算。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"))

你可能感兴趣的:(数据结构:Expression Tree)