python算法——字符串表达式的计算(转自:无限大地NLP_空木)
2017-08-20 14:42
507 查看
原文戳这里!!!
preface:最近有个面试,被要求给出一个字符串表达式,计算出结果。本以为是见到过的,想着用一个栈,然后被面试官打断说你这样是有问题的,然后想了说用树,又被打断说是有问题的,再仔细想想。结果还是没整出来。哎。回来翻了下leetcode发现有两道类似。
leetcode 224 Basic Calculator https://leetcode.com/problems/basic-calculator/有点类似,可这特么只用加减和括号不用乘除啊,妈的智障。这题用栈AC了。
leetcode 227 Basic Calculator II https://leetcode.com/problems/basic-calculator-ii/也有点类似,只是差了括号。
但这两道还是不够。翻书加上与同仁的讨论,发现只需要将表达式化为二叉树的后缀表达式即可,有了后缀表达式,就比较简单了。后缀表达式是能够唯一确定表达式树的。后序遍历表达式树即可。用栈对后缀表达式进行处理也可以的。主要还是需要将字符串表达式化为后缀表达式。
另外,计算字符串表达式,Python有个内置函数eval(),直接使用eval("1+2*(3-1)-4")即可。
coding:
[python] view
plain copy
# -*- coding: utf-8 -*-
"""
Created on Sun Jul 10 15:39:28 2016
@author: Administrator
"""
operator_precedence = {
'(' : 0,
')' : 0,
'+' : 1,
'-' : 1,
'*' : 2,
'/' : 2
}
def postfix_convert(exp):
'''''
将表达式字符串,转为后缀表达式
如exp = "1+2*(3-1)-4"
转换为:postfix = ['1', '2', '3', '1', '-', '*', '+', '4', '-']
'''
stack = [] #运算符栈,存放运算符
postfix = [] #后缀表达式栈
for char in exp:
# print char, stack, postfix
if char not in operator_precedence:#非符号,直接进栈
postfix.append(char)
else:
if len(stack) == 0:#若是运算符栈啥也没有,直接将运算符进栈
stack.append(char)
else:
if char == "(":
stack.append(char)
elif char == ")":#遇到了右括号,运算符出栈到postfix中,并且将左括号出栈
while stack[-1]!="(":
postfix.append(stack.pop())
stack.pop()
elif operator_precedence[char] > operator_precedence[stack[-1]]:
#只要优先级数字大,那么就继续追加
stack.append(char)
else:
while len(stack)!=0:
if stack[-1]=="(":#运算符栈一直出栈,直到遇到了左括号或者长度为0
break
postfix.append(stack.pop())#将运算符栈的运算符,依次出栈放到表达式栈里面
stack.append(char)#并且将当前符号追放到符号栈里面
while len(stack)!=0:#如果符号站里面还有元素,就直接将其出栈到表达式栈里面
postfix.append(stack.pop())
return postfix
#===========================这部分用于构造表达式树,不涉及计算================================#
class Node(object):
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def create_expression_tree(postfix):
"""
利用后缀表达式,构造二叉树
"""
stack = []
#print postfix
for char in postfix:
if char not in operator_precedence:
#非操作符,即叶子节点
node = Node(char)
stack.append(node)
else:
#遇到了运算符,出两个,进一个。
node = Node(char)
right = stack.pop()
left = stack.pop()
node.right = right
node.left = left
stack.append(node)
#将最后一个出了即可。
return stack.pop()
def inorder(tree):
if tree:
inorder(tree.left)
print tree.val
inorder(tree.right)
#=============================这部分用于计算值===================================#
def calculate(num1, op, num2):
if not num1.isdigit() and not num2.isdigit():
raise "num error"
else:
num1 = int(num1)
num2 = int(num2)
if op == "+":
return num1 + num2
elif op == "-":
return num1 - num2
elif op == "*":
return num1 * num2
elif op == "/":
if num2==0:
raise "zeros error"
else:
return num1/num2
else:
raise "op error"
def cal_expression_tree(postfix):
stack = []
for char in postfix:
stack.append(char)
if char in "+-*/":
op = stack.pop()
num2 = stack.pop()
num1 = stack.pop()
value = calculate(num1, op, num2)
value = str(value)#计算结果是数值类型,将其化为字符串类型
stack.append(value)
return int(stack[0])
if __name__=="__main__":
#另外异常情况的判断的话,可以使用try catch
exp = "1+2*(3-1)-4"
postfix = postfix_convert(exp)
#print "postfix:",postfix
#tree = create_expression_tree(postfix)
#inorder(tree)
print cal_expression_tree(postfix)
首先,运算符的优先级的定义operator_precedence字典的定义比较重要。遇到了(3-1*2)与(3*1-1)这两种情况,对三种运算符的优先级左右括号、减号、乘号,就不能简单的出栈进栈进行运算了。
其次,postfix_convert()函数将字符串表达式化为后缀表达式是关键。
最后,对于异常情况的处理,可以使用try catch,或者提前判断,这里在calculate()函数里面做了些判断。
主要参考:
Expression tree
《数据结构与高分笔记》P132
顺序堆栈应用--表达式计算
转载请认证:无限大地nlp_空木的博客
preface:最近有个面试,被要求给出一个字符串表达式,计算出结果。本以为是见到过的,想着用一个栈,然后被面试官打断说你这样是有问题的,然后想了说用树,又被打断说是有问题的,再仔细想想。结果还是没整出来。哎。回来翻了下leetcode发现有两道类似。
leetcode 224 Basic Calculator https://leetcode.com/problems/basic-calculator/有点类似,可这特么只用加减和括号不用乘除啊,妈的智障。这题用栈AC了。
leetcode 227 Basic Calculator II https://leetcode.com/problems/basic-calculator-ii/也有点类似,只是差了括号。
但这两道还是不够。翻书加上与同仁的讨论,发现只需要将表达式化为二叉树的后缀表达式即可,有了后缀表达式,就比较简单了。后缀表达式是能够唯一确定表达式树的。后序遍历表达式树即可。用栈对后缀表达式进行处理也可以的。主要还是需要将字符串表达式化为后缀表达式。
另外,计算字符串表达式,Python有个内置函数eval(),直接使用eval("1+2*(3-1)-4")即可。
coding:
[python] view
plain copy
# -*- coding: utf-8 -*-
"""
Created on Sun Jul 10 15:39:28 2016
@author: Administrator
"""
operator_precedence = {
'(' : 0,
')' : 0,
'+' : 1,
'-' : 1,
'*' : 2,
'/' : 2
}
def postfix_convert(exp):
'''''
将表达式字符串,转为后缀表达式
如exp = "1+2*(3-1)-4"
转换为:postfix = ['1', '2', '3', '1', '-', '*', '+', '4', '-']
'''
stack = [] #运算符栈,存放运算符
postfix = [] #后缀表达式栈
for char in exp:
# print char, stack, postfix
if char not in operator_precedence:#非符号,直接进栈
postfix.append(char)
else:
if len(stack) == 0:#若是运算符栈啥也没有,直接将运算符进栈
stack.append(char)
else:
if char == "(":
stack.append(char)
elif char == ")":#遇到了右括号,运算符出栈到postfix中,并且将左括号出栈
while stack[-1]!="(":
postfix.append(stack.pop())
stack.pop()
elif operator_precedence[char] > operator_precedence[stack[-1]]:
#只要优先级数字大,那么就继续追加
stack.append(char)
else:
while len(stack)!=0:
if stack[-1]=="(":#运算符栈一直出栈,直到遇到了左括号或者长度为0
break
postfix.append(stack.pop())#将运算符栈的运算符,依次出栈放到表达式栈里面
stack.append(char)#并且将当前符号追放到符号栈里面
while len(stack)!=0:#如果符号站里面还有元素,就直接将其出栈到表达式栈里面
postfix.append(stack.pop())
return postfix
#===========================这部分用于构造表达式树,不涉及计算================================#
class Node(object):
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def create_expression_tree(postfix):
"""
利用后缀表达式,构造二叉树
"""
stack = []
#print postfix
for char in postfix:
if char not in operator_precedence:
#非操作符,即叶子节点
node = Node(char)
stack.append(node)
else:
#遇到了运算符,出两个,进一个。
node = Node(char)
right = stack.pop()
left = stack.pop()
node.right = right
node.left = left
stack.append(node)
#将最后一个出了即可。
return stack.pop()
def inorder(tree):
if tree:
inorder(tree.left)
print tree.val
inorder(tree.right)
#=============================这部分用于计算值===================================#
def calculate(num1, op, num2):
if not num1.isdigit() and not num2.isdigit():
raise "num error"
else:
num1 = int(num1)
num2 = int(num2)
if op == "+":
return num1 + num2
elif op == "-":
return num1 - num2
elif op == "*":
return num1 * num2
elif op == "/":
if num2==0:
raise "zeros error"
else:
return num1/num2
else:
raise "op error"
def cal_expression_tree(postfix):
stack = []
for char in postfix:
stack.append(char)
if char in "+-*/":
op = stack.pop()
num2 = stack.pop()
num1 = stack.pop()
value = calculate(num1, op, num2)
value = str(value)#计算结果是数值类型,将其化为字符串类型
stack.append(value)
return int(stack[0])
if __name__=="__main__":
#另外异常情况的判断的话,可以使用try catch
exp = "1+2*(3-1)-4"
postfix = postfix_convert(exp)
#print "postfix:",postfix
#tree = create_expression_tree(postfix)
#inorder(tree)
print cal_expression_tree(postfix)
首先,运算符的优先级的定义operator_precedence字典的定义比较重要。遇到了(3-1*2)与(3*1-1)这两种情况,对三种运算符的优先级左右括号、减号、乘号,就不能简单的出栈进栈进行运算了。
其次,postfix_convert()函数将字符串表达式化为后缀表达式是关键。
最后,对于异常情况的处理,可以使用try catch,或者提前判断,这里在calculate()函数里面做了些判断。
主要参考:
Expression tree
《数据结构与高分笔记》P132
顺序堆栈应用--表达式计算
转载请认证:无限大地nlp_空木的博客
相关文章推荐
- python算法——字符串表达式的计算
- 算法笔试题整理——升级蓄水池 && 字符串数字表达式计算值 && 求旅游完所有景点需要的最少天数 && 宝箱怪
- leetcode 227. basic calculator 计算字符串表达式的值 python
- [算法 笔记]字符串表达式计算(简易版)
- Java中计算字符串表达式的好办法
- 输入一个字符串表达式,输出计算结果(队列、栈的应用)
- 计算4000000000内的最大f(n)=n值---字符串的问题python实现(五岁以下儿童)
- Delphi 如何计算字符串表达式呢?
- 设计一个算法判别用字符串表示的表达式中开、闭括号是否配对出现
- Python正则表达式如何进行字符串替换
- python再计算无限循环小数的循环节
- Python 输入时间字符串以分钟单位计算时间差
- 计算字符串中所有数字之和Python版
- Python中使用中文正则表达式匹配指定的中文字符串
- 给定一个字符串表达式s,计算其值(使用string和stack实现)
- python利用正则表达式提取字符串
- 从键盘上输入一个后缀表达式,试编写算法计算表达式的值。规定:逆波兰表达式的长度不超过一行,以$符作为输入结束,操作数之间用空格分隔,操作符只可能有+、-、*、/四种运算。例如:234 34+2*$。
- 我就给一个PHP逆波兰表达式的算法吧---工资计算专用
- 计算两个字符串相似度的算法
- python实现逆波兰计算表达式实例详解