中缀表达式转后缀表达式
学习过程
在网上查找资料,了解了中缀表达式和后缀表达式以及前缀表达式的定义。
中缀表达式:中缀表达式是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间。
例如:3*(5–2)+7/2
后缀表达式:后缀表达式,又称逆波兰式,指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则)。
例如:3 5 2 - * 7 2 / +
前缀表达式:前缀表达式又称波兰式,前缀表达式的运算符位于操作数之前。
中缀表达式应该处于中间状态,人们在日常生活中习惯性的表达式,然而在计算机里就不好处理了,比如遇到括号里面又有运算符,运算符的结合顺序等问题。因此我们就需要将中缀表达式进行转换。如果要运算的话,转化为后缀表达式只要从左往右进行相应的计算操作,而前缀表达式从右往左一样的操作即可。
题解思路
栈是后入先出的一种数据结构,用来存放式子的运算符等符号再合适不过。
查找资料,了解到了转化思路(只考虑四则运算):
- 从左往右扫描中缀表达式
- 遇到操作数放入字符数组s1
- ①遇到运算符比较和栈顶运算符的优先级:
-如果栈空或者栈顶是左括号, 直接压入栈中- 否则如果优先级比栈顶运算符的高,直接压入栈中
- 否则将栈的栈顶的运算符弹出并压入到s1中,再次转到①与栈中新的栈顶运算符相比较
- 遇到括号:
- 左括号:直接压入栈中
- 右括号:则依次弹出栈的栈顶的运算符,并压入s1,直到遇到左括号为止。括号要被丢弃,即右括号不用进栈,左括号最后弹出
- 扫描到表达式结束后,检查栈是否为空。不为空就全部弹出到s1中至空
- 输出s1
我的代码
class Stack:
def __init__(self):
self._item = []
# 添加元素
def push(self, item):
self._item.append(item)
# 方法变属性
@property
def size(self):
return len(self._item)
@property
def is_empty(self):
return not self._item
# 栈顶弹出
def pop(self):
return self._item.pop()
# 取栈顶元素
def peek(self):
return self._item[-1]
stack = Stack()
i = 0
s = []
s1 = input("请输入中缀表达式:")
print(f"中缀表达式:{s1}")
s1 = list(s1)
for ch in s1:
# 左括号入栈
if ch == '(':
stack.push(ch)
# 右括号栈的运算符出栈,放到后缀表达式
elif ch == ')':
# 前面一个是数字加空格
if str(s1[i-1]).isdigit():
s.append(' ')
while stack.peek() != '(':
s.append(stack.pop())
s.append(' ')
stack.pop() # 左括号弹出
# 四则运算符
# 优先级小于等于栈顶元素,栈顶元素出栈
elif ch == '+' or ch == '-':
# 前面一个是数字加空格
if str(s1[i - 1]).isdigit():
s.append(' ')
while not stack.is_empty and stack.peek() != '(':
s.append(stack.pop())
s.append(' ')
stack.push(ch)
elif ch == '*' or ch == '/':
# 前面一个是数字加空格
if str(s1[i - 1]).isdigit():
s.append(' ')
while (not stack.is_empty) and (stack.peek() == '*' or stack.peek() == '/'):
s.append(stack.pop())
s.append(' ')
stack.push(ch)
else:
# 当前是数字而前面一个不是数字的话加空格
if i > 0 and not str(s1[i-1]).isdigit():
s.append(' ')
# 数字直接添加
s.append(ch)
i = i + 1
while not stack.is_empty:
s.append(stack.pop())
s.append(' ')
print("后缀表达式:")
print(*s)