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