python 栈-解析四则运算公式

python 栈-解析四则运算公式

1、栈

也被称为下堆栈, 他是有序集合, 添加操作和移除操作发生在同一端,即顶端, 另一端称为底端

  • LIFO(last-in, first-out) 后进先出
  • 可用于反转排列顺序

栈的抽象数据类型

支持以下操作

  • push(item) 将元素添加到栈中
  • pop() 返回并删除顶端的元素
  • peek() 返回顶端的元素, 但不删除元素
  • isEmpty() 判断栈是否为空
  • size() 返回栈中的元素数量

解析算数表达式

  • 括号匹配: 每一个左括号都有与之对应的又括号, 并且括号有正确的嵌套关系

处理括号匹配
由空栈开始,从左往右依次处理括号。遇到左括号, 使用push操作将其加入栈中;如果遇到右括号就调用pop操作, 所有的左括号都应有右括号与之匹配。
处理完括号匹配,栈应该是空的

  • 前序表达式:运算符调整到两个操作数前, eg: +ab

  • 中序表达式:运算符出现在两个操作数间, eg: a*b

  • 后序表达式:运算符调整至操作数后, eg: ab+

  • 完全括号表达式: 对每一对运算符都添加一对括号, 由括号决定运算顺序, 杜绝歧义, 并且不需要记忆运算规则

    中序表达式 前序表达式 后序表达式
    a + b + a b a b +
    a - b / c - a / b c a b c / -
    a + b * c + d + a * b c + d a b c * + d +
    (a + b) * ( c + d) * + a b + c d a b + c d + *

中序转后序

  • 创建一个空栈和列表, 分别保存运算符和转换结果列表
  • 将中序表达式转换为一个列表
  • 从左往右扫描列表
    • 数值, 添加至转换列表中
    • 左括号, 压入栈中
    • 右括号, 重复从栈中获取元素,添加至转换结果列表中, 直至获取左括号
    • 运算符,将其与栈中的顶端元素比较,从栈中取出优先级高的元素追加至转换列表中
  • 处理完表达式后将栈中残余的运算符追加至转换结果列表中

后序表达式计算

  • 创建空栈
  • 将后续表达式转化为一个列表
  • 从左往右扫描列表
    • 数值,压入栈中
    • 运算符,从栈中去两个元素, 第一个为右数, 第二个为左数,计算出数值后重新压入栈中
  • 处理完表达式后, 从栈中获取数值

2、解析四则运算-Coding

后序表达式计算

# -*- coding: utf-8 -*-

"""
中序表达式转后序表达式, 并计算
"""
import re
import operator
import string


class PostOrderConversion:

    def conversionToPostOrder(self, inOrdErexpr):
        """
        后序转换
        """
        # 构建运算符优先级字典
        prec = {
            "*": 3,
            "/": 3,
            "+": 2,
            "-": 2,
            "(": 1,
            ")": 1
        }

        if not self.parseChecker(inOrdErexpr):
            raise ValueError

        opStack = Stack()
        postOrderList = list()
        exprList = inOrdErexpr.split()

        for ch in exprList:
            if ch.isdigit():
                postOrderList.append(ch)
            elif ch == "(":
                opStack.push(ch)
            elif ch == ")":
                topOper = opStack.pop()
                while topOper != "(":
                    postOrderList.append(topOper)
                    topOper = opStack.pop()
            else:
                # 比较运算符优先级,如果栈中运算符的优先级>当前运算符, 追加至转换列表中
                while (not opStack.isEmpty()) and (prec[opStack.peek()] > prec[ch]):
                    postOrderList.append(opStack.pop())
                opStack.push(ch)
        # 将栈中的运算符追加至转换列表中
        while not opStack.isEmpty():
            postOrderList.append(opStack.pop())
        return "".join(postOrderList)

    def calculatePostOrderFormulas(self, postOrderformulas):
        """
        计算后序表达式
        """
        operaDict = {
            "+": operator.add,
            "-": operator.sub,
            "*": operator.mul,
            "/": operator.truediv
        }
        postStack = Stack()
        postOrderList = list(postOrderformulas)
        for ch in postOrderList:
            if ch.isdigit():
                postStack.push(eval(ch))
            else:
                opN1 = postStack.pop()
                opN2 = postStack.pop()
                postStack.push(operaDict[ch](opN2, opN1))
        return postStack.pop()

    def parseChecker(self, symbolStr):
        """
        判断括号是否完全匹配
        """
        symbolStr = self.extractBrackets(symbolStr)
        s = Stack()
        balanced = True
        index = 0
        while index < len(symbolStr) and balanced:
            symbol = symbolStr[index]
            if symbol in "{[(":
                s.push(symbol)
            elif s.isEmpty():
                balanced = False
            else:
                topSym = s.pop()
                if self.matches(topSym, symbol):
                    balanced = False
            index += 1
        if balanced and s.isEmpty():
            return True
        else:
            return False

    def extractBrackets(self, formulas):
        regex = re.compile(r'[{\[()\]}]')
        return "".join(regex.findall(formulas))

    def matches(self, open, close):
        opens = "{[("
        closers = "}])"
        return opens.index(opens) == closers.index(close)

if __name__ == "__main__":
    formulas1 = "( 1 + 2 ) * 3"
    formulas2 = "5 + 6 * 7"
    postConversion = PostOrderConversion()
    cFormulas1 = postConversion.conversionToPostOrder(formulas1)
    cFormulas2 = postConversion.conversionToPostOrder(formulas2)
    print("formulas1: %s | formulas1: %s" % (cFormulas1, cFormulas1))
    print("formulas1: %s=" % formulas1, postConversion.calculatePostOrderFormulas(cFormulas1))
    print("formulas2: %s=" % formulas2, postConversion.calculatePostOrderFormulas(cFormulas2))


计算结果

扫描二维码关注公众号,回复: 11575007 查看本文章
formulas1: 12+3* | formulas1: 12+3*
formulas1: ( 1 + 2 ) * 3= 9
formulas2: 5 + 6 * 7= 47

创建栈

# -*- coding: utf-8 -*-


class Stack():

    def __init__(self):
        self.items = list()

    def isEmpty(self):
        return self.items == []

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def peek(self):
        return self.items[-1]

    def size(self):
        return len(self.items)


if __name__ == "__main__":
    stack = Stack()
    stack.push(1)
    stack.push(2)
    stack.push(3)
    stack.push(4)
    print(stack.items)
    print(stack.peek())
    print(stack.isEmpty())

猜你喜欢

转载自blog.csdn.net/qq_40601372/article/details/107325205