您的位置:首页 > 理论基础 > 数据结构算法

PKU数据结构与算法Python版--习题总结(7)--中缀表达式求值

2020-04-19 23:13 330 查看

1、题目

描述

通过把“中缀转后缀”和“后缀求值”两个算法功能集成在一起(非简单的顺序调用),实现对中缀表达式直接求值,新算法还是从左到右扫描中缀表达式,
但同时使用两个栈,一个暂存操作符,一个暂存操作数,来进行求值。

输入输出示例

输入样例1:
( 2 + 3 ) * 6 + 4 / 2
输出样例1:
32.0

输入样例2:
2 ^ 3 + 4 * 5 - 16 / 2
输出样例2:
20.0

输入样例3:
( 5 + 1 ) * 2 / 3 - 3 ^ ( 2 + 8 / 4 ) / 9 + 6
输出样例3:
1.0

2、思路

创建一个函数,接受参数为一个字符串,即一个中缀表达式,
其中每个数字或符号间由一个空格隔开;
返回一个整数,即求值的结果。(支持 + - * / ^ 五种运算)
其中“ / ”定义为真除True DIV,结果是浮点数类型

小技巧:

只需要把中缀表达式转化为后缀表达式中涉及’把操作符加入待输出列表‘的操作改为’从存储操作数的栈中pop两个元素进行运算并压入栈中‘的操作。

3、代码

#栈的实现(利用List)
class Stack:
def __init__(self):
self.items = []

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[len(self.items) - 1]

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

#定义计算的主函数,返回值时float类型
def calculate(s) -> float:
#定义运算函数,用于计算+-*/^运算
def doMath(op,op1,op2):
if op=='*':
return op1 * op2
elif op=='/':
return op1 / op2
elif op=='+':
return op1 + op2
elif op=='^':
return op1**op2
else:
return op1 - op2
#创建一个字典,用来比较各个运算符的优先级
prec={}
prec['^']=4
prec['/']=3
prec['*']=3
prec['-']=2
prec['+']=2
prec['(']=1

#创建一个空栈,用来存储运算符。包括+-*/^和(
opStack=Stack()
#创建一个空栈,用来存储运算数
operandStack=Stack()
#创建一个列表,将传入的字符串转化为由token组成的列表
tokenList=s.split()
#遍历由token组成的列表
for token in tokenList:
#如果是运算数,压入存储运算数的栈中
if token not in '^/*-+()':
operandStack.push(int(token))
#如果是左括号,压入存储运算符的栈中
elif token=='(':
opStack.push(token)
#如果是右括号,把存储运算符的栈顶元素逐个pop出来,直到栈顶元素是左括号。
#pop出来的运算符与存储运算数的离栈顶最近的两个元素进行运算,结果压入存储运算数的栈中。
elif token==')':
topToken=opStack.pop()
while topToken!='(':
operand2=operandStack.pop()
operand1=operandStack.pop()
result=doMath(topToken,operand1,operand2)
operandStack.push(result)

topToken=opStack.pop()
#是运算符,当存储运算符的栈不空且栈顶元素优先级大于它时,栈顶元素逐个pop出来,直到栈顶元素优先级小于它
#pop出来的运算符与存储运算数的离栈顶最近的两个元素进行运算,结果压入存储运算数的栈中。
else:
while (not opStack.isEmpty()) and (prec[opStack.peek()]>=prec[token]):
operand2=operandStack.pop()
operand1=operandStack.pop()
result=doMath(opStack.pop(),operand1,operand2)
operandStack.push(result)
#把这个运算符压入存储运算符的栈中
opStack.push(token)
#如果存储运算符的栈中不空,将存储运算符的栈中元素逐个pop出来
#pop出来的运算符与存储运算数的离栈顶最近的两个元素进行运算,结果压入存储运算数的栈中。
while not opStack.isEmpty():
operand2=operandStack.pop()
operand1=operandStack.pop()
result=doMath(opStack.pop(),operand1,operand2)
operandStack.push(result)
#返回与存储运算数的栈中最后剩下的元素,即为结果
return operandStack.pop()

# 代码结束

# 调用检验
print("======== 1-calculate ========")
print(calculate("( 2 + 3 ) * 6 + 4 / 2"))
print(calculate("2 ^ 3 + 4 * 5 - 16 / 2"))
print(calculate("( 5 + 1 ) * 2 / 3 - 3 ^ ( 2 + 8 / 4 ) / 9 + 6"))
  • 点赞
  • 收藏
  • 分享
  • 文章举报
zjx-pku 发布了17 篇原创文章 · 获赞 0 · 访问量 344 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: