preface:最近有個面試,被要求給出乙個字串表示式,計算出結果。本以為是見到過的,想著用乙個棧,然後被面試官打斷說你這樣是有問題的,然後想了說用樹,又被打斷說是有問題的,再仔細想想。結果還是沒整出來。哎。回來翻了下leetcode發現有兩道類似。
leetcode 224 basic calculator 有點類似,可這特麼只用加減和括號不用乘除啊,媽的智障。這題用棧ac了。
leetcode 227 basic calculator ii 也有點類似,只是差了括號。
但這兩道還是不夠。翻書加上與同仁的討論,發現只需要將表示式化為二叉樹的字尾表示式即可,有了字尾表示式,就比較簡單了。字尾表示式是能夠唯一確定表示式樹的。後序遍歷表示式樹即可。用棧對字尾表示式進行處理也可以的。主要還是需要將字串表示式化為字尾表示式。
另外,計算字串表示式,python有個內建函式eval(),直接使用eval("1+2*(3-1)-4")即可。
coding:
# -*- coding: utf-8 -*-
"""created on sun jul 10 15:39:28 2016
@author: administrator
"""operator_precedence =
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:#非符號,直接進棧
else:
if len(stack) == 0:#若是運算子棧啥也沒有,直接將運算子進棧
else:
if char == "(":
elif char == ")":#遇到了右括號,運算子出棧到postfix中,並且將左括號出棧
while stack[-1]!="(":
stack.pop()
elif operator_precedence[char] > operator_precedence[stack[-1]]:
#只要優先順序數字大,那麼就繼續追加
else:
while len(stack)!=0:
if stack[-1]=="(":#運算子棧一直出棧,直到遇到了左括號或者長度為0
break
while len(stack)!=0:#如果符號站裡面還有元素,就直接將其出棧到表示式棧裡面
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)
else:
#遇到了運算子,出兩個,進乙個。
node = node(char)
right = stack.pop()
left = stack.pop()
node.right = right
node.left = left
#將最後乙個出了即可。
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:
if char in "+-*/":
op = stack.pop()
num2 = stack.pop()
num1 = stack.pop()
value = calculate(num1, op, num2)
value = str(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
順序堆疊應用--表示式計算
shell 字串 表示式
在shell程式設計中,經常要處理一些字串變數。比如,計算長度啊 擷取子串啊 字元替換啊等等,常常要用到awk expr sed tr等命令。下面給大家介紹個簡單的字串處理方法,用不著巢狀複雜的子命令。計算value字串的字元數量。或 刪除value字串中以分隔符 匹配的右邊字元,保留左邊字元。或 ...
字串 表示式求值
不曾想到我居然還會寫這種部落格,然而自己是真的對這些模擬很噁心。這簡單,可以遞迴求解,遇到乙個符號,直接往下遞迴。這裡我的處理是有空格的,因此呢可以使用atof將字串轉化了double,atoi好像是轉化為int。include include include include include inc...
Python 字串與正規表示式
alist list range 1 1001 blist list map str alist cstr join blist dstr cstr str sum range 1 1001 print dstr open text.txt w write dstr import os print ...