• 05_2.栈的应用--表达式的计算和变换


    后缀表达式的计算:

    class ESStack(SStack):
        """SStack参考05.栈"""
        def depth(self):
            return len(self._elems)
    
    
    def suf_exp_evaluator(exp):
        """后缀表达式计算"""
        operators = "+-*/"
        st = ESStack()
        for x in exp:
            if x not in operators:
                st.push(float(x))
                continue
            if st.depth() < 2:
                raise SyntaxError("Short of operand(s).")
            b = st.pop()
            a = st.pop()
            if x == "+":
                c = a + b
            elif x == "-":
                c = a - b
            elif x == "*":
                c = a * b
            elif x == "/":
                c = a / b
            else:
                break
            st.push(c)
        if st.depth() == 1:
            return st.pop()
        raise SyntaxError("Extra operand(s).")
    
    
    def suffix_exp_evaluator(line):
        """表达式的每一项用空格隔开
        如:计算11+12
        应输入:11 12 +
        """
        return suf_exp_evaluator(line.split())
    
    
    def suffix_exp_calculator():
        """表达式交互"""
        while 1:
            try:
                line = input("Suffix Expression:")
                if line == "exit":return
                res = suffix_exp_evaluator(line)
                print(res)
            except Exception as ex:
                print("Error:", type(ex), ex.args)
    
    
    if __name__ == '__main__':
        suffix_exp_calculator()

    中缀表达式转换为后缀表达式:

    def trans_infix_suffix(line):
        """中缀表达式转换为后缀表达式"""
        infix_operators = "+-*/()"
        priority = {"(": 1, "+": 3, "-": 3, "*": 5, "/": 5}
        st = SStack()
        exp = []
        for x in tokens(line):
            if x not in infix_operators:  # 遇到操作数时,将加入exp;
                exp.append(x)
            elif st.is_empty() or x == '(':  # 如果st为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈
                st.push(x)
            elif x == ')':  # 遇到右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
                while not st.is_empty() and st.top() != '(':
                    exp.append(st.pop())
                if st.is_empty():
                    raise SyntaxError("Missing '('.")
                st.pop()
            else:  # 若x优先级比栈顶运算符的高,直接将运算符压入栈,否则将栈顶的运算符弹出并加入到exp中,重复比较x与栈顶
                while (not st.is_empty() and priority[st.top()] >= priority[x]):
                    exp.append(st.pop())
                st.push(x)
        while not st.is_empty():
            if st.top() == '(':
                raise SyntaxError("Extra '('.")
            exp.append(st.pop())  # 栈中剩余的运算符依次弹出并加入exp
        return exp
    
    
    def tokens(line):
        """ 生成器函数
            逐一生成line中的一个个项,不处理一元运算符,也不能处理带符号的浮点数
        """
        infix_operators = "+-*/()"
        line = line.strip()
        i, llen = 0, len(line)
        while i < llen:
            while line[i].isspace():  # 检测字符串是否只由空格组成
                i += 1
            if i >= llen:
                break
            if line[i] in infix_operators:  # 运算符的情况
                yield line[i]
                i += 1
                continue
            j = i + 1  # 下面处理运算对象
            # 数字是按空格分开的 如:11 就是11  ,1  1 就会处理成1与1
            while (j < llen and not line[j].isspace() and line[j] not in infix_operators):
                # 如果出现E或e,后面可以有一个负的指数部分 2e2 就是2*100
                if ((line[j] == 'e' or line[j] == 'E') and j + 1 < llen and line[j + 1] == '-'):
                    j += 1
                j += 1
            yield line[i:j]
            i = j
    
    
    def test_trans_infix_suffix(s):
        print(s)  # 中缀表达式
        print(trans_infix_suffix(s))  # 后缀表法式
        # 调用后缀表法式计算函数计算结果
        print("Value:", suf_exp_evaluator(trans_infix_suffix(s)))  # 计算结果
    
    
    if __name__ == '__main__':
        # suffix_exp_calculator()
        test_trans_infix_suffix("10*(3e-1 + 1) - 1 ")  # 12.0
        # 10*(3e-1 + 1) - 1
        # ['10', '3e-1', '1', '+', '*', '1', '-']
  • 相关阅读:
    HTTP基础及telnet简单命令
    【详解】并查集高级技巧:加权并查集、扩展域并查集
    二叉树中两节点的最近公共父节点(360的c++一面问题)
    (用POJ 1160puls来讲解)四边形不等式——区间dp的常见优化方法
    详细讲解Codeforces Round #625 (Div. 2)E
    详细讲解Codeforces Round #625 (Div. 2) D. Navigation System
    详细讲解Codeforces Round #624 (Div. 3) F. Moving Points
    详细讲解Codeforces Round #624 (Div. 3) E. Construct the Binary Tree(构造二叉树)
    POJ
    新手建站前需要做哪些准备?
  • 原文地址:https://www.cnblogs.com/fly-book/p/11718143.html
Copyright © 2020-2023  润新知