3.python实现数据结构-栈

基本栈结构

class Stack(object):
    def __init__(self, max_size):
        self.max_size = max_size
        self.data = []

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

    def is_full(self):
        return self.size() >= self.max_size

    def push(self, data):
        if not self.is_full():
            self.data.append(data)

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

    def peek(self):
        return None if self.size() == 0 else self.data[-1]

    def is_empty(self):
        return self.size() == 0

    def print(self):
        if not self.is_empty():
            for i in range(len(self.data) - 1, -1, -1):
                print(self.data[i], end='->')


if __name__ == '__main__':
    stack = Stack(5)
    stack.push(1)
    # stack.push(2)
    # stack.push(3)
    # stack.push(4)
    # stack.push(5)
    # stack.print()
    print(stack.peek())
    print(stack.size())
    print(stack.pop())
    print(stack.peek())
    print(stack.size())
    

基于栈结构的逆波兰计算器的实现

实现核心后缀表达式

后缀表达式,又称逆波兰表达式,因为前缀表达式并不如何人类的阅读习惯,所有出现了后缀表达式,从左往右依次计算,最终堆栈的最后一个数即为结果

  1. 例如 1 + ( ( 2 + 3 )* 4) - 5 转为逆波;兰表达式为 1 2 3 + 4 * + 5 -
  2. 后缀表达式的计算规则为如遇到数字直接push到堆栈如遇到操作符从堆栈中弹出2个数计算完之后重新压入堆栈直到堆栈只有一个数
    1. 逆波兰表达式计算规则 1 2 3 数字 压入 堆栈
    2. 遇到+号操作符 弹出2个数字 3 2 计算得到 5 压入堆栈 其次堆栈从栈底到栈顶依次为 1 5
    3. 遇到数字4压入 1 5 4
    4. 遇到*号操作符 弹出 4 5 计算 20 压入 此时为 1 20
    5. 遇到+号 弹出 20 1 计算 21 压入 21
    6. 遇到数字5 压入 21 5
    7. 遇到-号操作符 弹出 5 21后面一个数减去前面一个数即 21 - 5 得到16
  3. 中缀表达式转后缀表达式
    1. 首先初始化两个栈stack,运算符栈stack1 和中间结果栈stack s2
    2. 从左往右开始扫描中缀表达式
    3. 遇到数字直接压入 s2
    4. 遇到操作符需要做特殊处理
      1. 如果是左括号( 直接压入s1
      2. 如果是右括号 ) 需要从左边s1中依次弹出若干操作符压入s2 直到遇到 左括号)为止,并且最后叫匹配的左括号弹出 即消除了一对括号
      3. 如果是正常操作符
        1. 如果当前操作符的优先级大于 s1中栈顶的优先级 则直接压入s1
        2. 如果s1为空 或者 s1的栈顶为 左括号( 直接压入s1
        3. 如果当前操作符优先级小于等于 s1栈顶操作符的优先级,则从s1的栈顶弹出操作符并压入到s2中,一直循环操作第三步,即一直进行到s1为空或者s1栈顶的操作符优先级小于了当前操作符,最终将当前操作符压入到s1中
    5. 最终将s1中剩余的所有操作符依次弹出压入s2
    6. 最终将s2的栈数据反转即(从栈底到栈顶)得到中缀表达式
import re


class PolandCalculator:
    def __init__(self, expression):
        self.expression = expression
        self.poland_expression_list = self.parse_poland_expression()

    @staticmethod
    def get_priority(operator):
        return 1 if operator in ['*', '/'] else 0

    def parse_poland_expression(self):
        poland_str = self.expression.split(' ')
        # 初始化两个栈:运算符栈s1和储存中间结果的栈s2;
        s1, s2 = [], []
        # 从左至右扫描中缀表达式
        for item in poland_str:
            # 如果是数字直接加入s2
            if re.match('^[0-9]*$', item):
                s2.append(item)
            # 操作符和括号
            else:
                # 括号处理
                if item == '(':
                    # 左括号直接入栈
                    s1.append(item)
                elif item == ')':
                    # 如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
                    while s1[-1] != '(':
                        s2.append(s1.pop())
                    # 消除左括号
                    s1.pop()
                else:
                    # 操作符处理
                    if s1 == [] or s1[-1] == '(':
                        # 如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
                        s1.append(item)
                    elif self.get_priority(item) > self.get_priority(s1[-1]):
                        # 若优先级比栈顶运算符的高,也将运算符压入s1
                        s1.append(item)
                    else:
                        while len(s1) > 0 and self.get_priority(s1[-1]) <= self.get_priority(item):
                            # 否则,将s1栈顶的运算符弹出并压入到s2中,直到s1为空或者遇到一个比当前操作符优先级小的
                            s2.append(s1.pop())
                        s1.append(item)

        while len(s1) > 0:
            s2.append(s1.pop())
        return s2

    def calc(self):
        print(self.poland_expression_list)
        result = []
        # 循环遍历 后缀表达式 如果是数字直接压入栈 如果是操作符 从result栈中弹出2个数字进行操作 如果是- 或者 /
        # 第二个弹出的操作数 作为被减数 或者 被除数 然后结果再压入栈中
        # 最终的结果是 result 栈中最后一个值
        for i in range(len(self.poland_expression_list)):
            exp = self.poland_expression_list[i]
            if re.match('^[0-9]*$', exp):
                result.append(exp)
            else:
                num1 = int(result.pop())
                num2 = int(result.pop())
                if exp == '+':
                    result.append(num1 + num2)
                elif exp == '-':
                    result.append(num2 - num1)
                elif exp == '*':
                    result.append(num2 * num1)
                elif exp == '/':
                    result.append(num2 / num1)
        return result[0]


if __name__ == '__main__':
    calculator = PolandCalculator('1 + ( ( 2 + 3 ) * 4 ) - 5')
    print(calculator.calc())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值