中缀表示形式的整数简单算术表达式求值
1. 题目
设有一个算术表达式为:a+b*(c-d)+b/d,其中a,b,c,d均为整数,且d不为0,请完成表达式求值运算,并把计算结果输出屏幕。
2. 算法思想
该解法一个分为三个部分,它们分别是:创建一个栈类,创建一个可将中缀表达式转换为后缀表达式的函数和创建一个可以对后缀表达式进行求值的函数。
其具体步骤为:
2.1 建立一个栈类,可以用于实例化一个空栈,类中也有5个方法,分别是:判断栈是否为空,加入元素,弹出元素,返回栈顶元素和返回栈的大小
2.2 定义一个可判别操作码优先级的函数,其中“(”的优先级最小,为1;“+”与“-”优先级为2;“*”和“/”优先级为3;“)”优先级为4.
2.3 创建一个可将中缀表达式转换为后缀表达式的函数,首先创建一个空栈,并对输入的字符串形式的表达式进行字符遍历,对于每个元素的操作情况如下:
a. 若元素为运算数,则直接输出。
b. 若栈为空,且该元素为操作码,其不为左右括号,则可以将元素直接压入栈中。
c. 如果操作码为左括号,直接压入栈。
d. 如果操作码为右括号,将栈顶的运算符弹出并输出,直到遇到左括号(出栈,不输出)
e. 对于非括号类的操作码:
若优先级大于栈顶运算符时,将它压栈。
若优先级小于等于栈顶运算符时,将栈顶运算符弹出并输出;再比较新的栈顶运算符,直到运算符大于栈顶运算符优先级为止,然后将该运算符压栈。
f. 当各元素处理完毕,则把栈中存留的运算符一并输出。
g. 由于左括号不应输出,那么将后缀表达式中的左括号去除。
2.4 创建一个可以对后缀表达式进行求值的函数,同理,首先创建一个空栈,并对输入的字符串形式的表达式进行字符遍历,对于每个元素的操作情况如下:
a. 当元素为数字时,压栈。
b. 当元素为操作码时,先将栈中的前两个元素(注意这两个操作数的运算顺序!)弹出,并作对应的运算,将一次运算得出的结果送入栈中。
c. 在栈中的最后一个元素即为最终运算结果
2.5 设置主函数,对函数输入,并检测输出
3. 具体实现
3.1 创建一个栈类
class Stack(object):
"""栈的实现"""
def __init__(self):
self.items = []
def is_empty(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)
3.2 定义一个可判别操作码优先级的函数
def priority(op):
"""定义一个可判别操作码优先级的函数"""
global temp
if op == '(':
temp = 1
elif op == '+':
temp = 2
elif op == '-':
temp = 2
elif op == '*':
temp = 3
elif op == '/':
temp = 3
elif op == ')':
temp = 4
return temp
3.3 创建一个可将中缀表达式转换为后缀表达式的函数
def infix_to_postfix(expr):
"""将中缀表达式转换为后缀表达式"""
new_expr = ''
#创建一个空栈
st = Stack()
for ele in expr:
#若元素为运算数,则直接输出
if ele.isdigit():
new_expr+=ele
#若栈为空,且该操作码不为左右括号,则可以将元素直接压入栈中
elif st.is_empty() and ele != "(" and ele != ')':
st.push(ele)
else:
#如果操作码为左括号,直接压入栈
if ele == "(":
st.push(ele)
#如果操作码为右括号,将栈顶的运算符弹出并输出,直到遇到左括号(出栈,不输出)
elif ele == ")":
while True:
if st.is_empty():
break
elif st.peek() != "(":
new_expr+=st.pop()
elif st.peek() == "(":
st.pop()
else:
"""对于运算符:
若优先级大于栈顶运算符时,将它压栈。
若优先级小于等于栈顶运算符时,将栈顶运算符弹出并输出;
再比较新的栈顶运算符,直到运算符大于栈顶运算符优先级为止,
然后将该运算符压栈
"""
prior = priority(ele)
peek = st.peek()
peek_prior = priority(peek)
if prior > peek_prior:
st.push(ele)
else:
new_expr+=st.pop()
while True:
if st.is_empty():
break
elif prior<=priority(st.peek()):
new_expr+=st.pop()
else:
break
st.push(ele)
#当各元素处理完毕,则把栈中存留的运算符一并输出
while True:
if not st.is_empty():
new_expr+=st.pop()
else:
break
#由于左括号不应输出,那么将后缀表达式中的左括号去除
return new_expr.replace("(","")
3.4 创建一个可以对后缀表达式进行求值的函数
def cal_post(post):
"""利用后缀表达式求值"""
#先创建一个空栈
st = Stack()
#对后缀表达式各个字符进行遍历
for ele in post:
#当元素为数字时,压栈
if ele.isdigit():
st.push(ele)
else:
#当元素为操作码时,先将栈中的前两个元素弹出,并作对应的运算
right = int(st.pop())
left = int(st.pop())
if ele == "+":
res = left + right
elif ele == '-':
res = left - right
elif ele == '*':
res = left * right
elif ele == '/':
res = left / right
#将一次运算得出的结果送入栈中
st.push(res)
#在栈中的最后一个元素即为最终运算结果
return st.pop()
3.5 设置主函数
def main():
expression = input("请输入一个合法的表达式:")
res = cal_post(infix_to_postfix(expression))
print("运算结果为:"+str(res))
4. 实测结果
输入
main()
请输入一个合法的表达式:1+2*(7-4)+9/3
输出
运算结果为:10
本人第一次写博客,请各位大佬批评指点!