python 表达式求值数据结构_python 数据结构与算法
python 數據結構與算法
1 python常見數據結構性能
1.1 List
1.1.1 安索引取值和賦值
1.1.2 列表append和__add__()
1.1.3 使用timeit模塊測試執行時間
1.1.4 List基本操作的大O數量級
1.2 Dict
1.2.1 dict數據類型
2 線性結構 Linear Structure
2.1 棧Stack
2.1.1 抽象數據類型Stack
2.1.2 Stack的操作如下
2.1.3 棧的應用1:簡單括號匹配
2.1.3.1 圓括號匹配
2.1.3.2 通用括號匹配
2.1.4 棧的應用2:進制轉換
2.1.4.1 十進制轉換二進制
2.1.4.2 十進制轉換任意進制
2.1.5 棧的應用3:表達式轉換
2.1.5.1 中綴表達式
2.1.5.2 全括號中綴表達式
2.1.5.3 前綴和后綴表達式
2.1.5.4 中綴表達式轉換為前綴和后綴形式
2.1.5.5 通用的中綴轉后綴算法
2.1.5.6 后綴表達式求值
2.2 隊列Queue
1 python常見數據結構性能
1.1 List
1.1.1 安索引取值和賦值
list最常用的操作是:按索引取值和賦值(v=a[i],a[i]=v),這兩個操作執行時間與列表大小無關,均為O(1)。
1.1.2 列表append和__add__()
list.addend(v),執行時間是O(1)。
list0 = list1 + [v],執行時間是O(n+k),其中k是被加的列表長度。
1.1.3 使用timeit模塊測試執行時間
使用timeit模塊對函數計時:
1.1.4 List基本操作的大O數量級
1.2 Dict
1.2.1 dict數據類型
字典是根據key找到對應的value,最常用的取值get和賦值set,其性能都是O(1)。另外一個常用的操作判斷字典中是否存在某個key (in),這個性能也是O(1)。
2 線性結構 Linear Structure
線性結構是一種有序數據項的集合,其中每個數據項都有唯一的前驅和后繼(除了第一個和最后一個)。
2.1 棧Stack
棧是一種有次序的數據項集合,在棧中,數據項的加入和移除都僅發生在同一端,這一端叫做“棧頂top”,另一端叫做“棧底base”。
棧是一種后進先出LIFO:Last in First out,這是一種基于數據項保存時間的次序,時間越短的離棧頂越近,而時間越長的離棧底越近。
2.1.1 抽象數據類型Stack
抽象數據類型“棧”是一個有次序的數據集,每個數據項僅從“棧頂”一端加入到數據集中、從數據集中移除,棧具有后進先出LIFO的特性。
2.1.2 Stack的操作如下
stack():創建一個空棧,不包含任何數據項。
push(item):將item加入棧頂,無返回值。
pop():將棧頂的數據項移除,并返回,棧被修改。
peek():“窺視”棧頂數據項,返回棧頂的數據。
isEmpty():返回是否是空棧。
size():返回棧中有多少個數據項。
class Stack(object):
def __init__(self):
self.stack = []
def push(self, item):
self.stack.append(item)
def pop(self):
if not self.is_empty():
return self.stack.pop()
def peek(self):
if not self.is_empty():
return self.stack[self.size()-1]
def is_empty(self):
return len(self.stack) == 0
def size(self):
return len(self.stack)
2.1.3 棧的應用1:簡單括號匹配
2.1.3.1 圓括號匹配
括號必須遵循“平衡”原則,即每個開括號必須有一個比括號對應。
從左到右掃描括號,最新打開的左括號,應該匹配最先遇到的右括號。這樣,第一個左括號就應該匹配最后一個右括號,這種次序反轉的識別,正好符合棧的特性。
流程圖如下:
from data_structure.Stack.stack import Stack
def brackets_valid(expression):
stack = Stack()
for item in expression:
if item == "(":
stack.push(item)
elif item == ")":
if stack.is_empty():
return False
else:
stack.pop()
return stack.is_empty()
if __name__ == '__main__':
print(brackets_valid("()()()"))
print(brackets_valid("(()())(()"))
print(brackets_valid("((5+6)*(4+3))+((10-9)"))
2.1.3.2 通用括號匹配
實際應用中,會遇到更多種括號,比如:[], {},()。
from data_structure.Stack.stack import Stack
def brackets_valid(expression):
stack = Stack()
mapping = {
")": "(",
"]": "[",
"}": "{"
}
for item in expression:
if item in "([{":
stack.push(item)
elif item in ")]}":
if stack.is_empty():
return False
else:
if stack.peek() != mapping[item]:
return False
else:
stack.pop()
return stack.is_empty()
if __name__ == '__main__':
print(brackets_valid("()()()"))
print(brackets_valid("(()())(()"))
print(brackets_valid("((5+6)*(4+3))+((10-9)"))
print(brackets_valid("{{([][])}()}"))
print(brackets_valid("[[{{(())}}]]"))
print(brackets_valid("[][][](){}"))
print(brackets_valid("([)}"))
print(brackets_valid("((()]))"))
print(brackets_valid("[{()]"))
2.1.4 棧的應用2:進制轉換
進制:指用多少字符來表示整數。十進制是0-9十個數字字符,二進制是0、1兩個字符。
例如:十進制233對應的二進制是11101001,具體算法如下:
233 = 2102 + 3101 + 3100
11101001 = 127 + 126 + 125 + 024 + 123 + 022 +021 + 1*20
2.1.4.1 十進制轉換二進制
常見的十進制轉換二進制采用的是**“除2求余數”的算法。如下:35的二進制是100011。在除2求余的過程中,得到的余數是從低到高的次序,而輸出則是從高到低,所以需要一個棧來反轉次序**。
from data_structure.Stack.stack import Stack
def convert(num):
if not isinstance(num, int):
return False
stack = Stack()
while num:
num, remainder = divmod(num, 2)
stack.push(remainder)
result = ""
while not stack.is_empty():
result += str(stack.pop())
return result
if __name__ == '__main__':
print(f"35的二進制數是{convert(35)}")
2.1.4.2 十進制轉換任意進制
將“除2求余”改為“除N求余”就可以將上面的算法擴展為任意進制轉換。
十進制233對應八進制351,十六進制是E9。
主要區別是:
二進制:0-1
十進制:0-9
八進制:0-7
十六進制:0-9,A-F
from data_structure.Stack.stack import Stack
def convert(num, unit):
if not isinstance(num, int):
return False
dights = "0123456789ABCDEF"
stack = Stack()
while num:
num, remainder = divmod(num, unit)
stack.push(remainder)
result = ""
while not stack.is_empty():
result += str(dights[stack.pop()])
return result
if __name__ == '__main__':
print(f"35的二進制數是{convert(35, 2)}")
print(f"233的八進制數是{convert(233, 8)}")
print(f"233的十六進制數是{convert(233, 16)}")
2.1.5 棧的應用3:表達式轉換
2.1.5.1 中綴表達式
操作符位于兩個操作數之間的表示法,稱為“中綴”表達式。例如:A+B。
2.1.5.2 全括號中綴表達式
計算機處理時最好避免復雜的優先級(乘除優先于加減、括號優先級)規則,能明確規定所有的計算順序是最好的。因此,引入全括號表達式: ((A+B*C)+D)
2.1.5.3 前綴和后綴表達式
前綴表達式:將操作符移到操作數前面,即:+AB。
后綴表達式:將操作符移到操作數后面,即:AB+。
在前綴和后綴表達式中,操作符次序完全決定了運算的次序,不再混淆。
2.1.5.4 中綴表達式轉換為前綴和后綴形式
2.1.5.5 通用的中綴轉后綴算法
中綴表達式A+BC,對應的后綴表達式是 ABC+。其中,操作數ABC的順序沒有改變,操作符的出現順序在后綴表達式中反轉了。由于*的優先級比+高,所以后綴表達式中操作符的出現順序與運算次序一致。
算法流程:
import string
from data_structure.Stack.stack import Stack
def convert_postfix(expression):
result = ""
oper_stack = Stack()
priority = {
"(": 0,
"+": 1,
"-": 1,
"*": 2,
"/": 2
}
for item in expression:
if item in string.ascii_letters or item in string.digits:
result += item
elif item == "(":
oper_stack.push(item)
elif item == ")":
while oper_stack.peek() != "(":
result += oper_stack.pop()
else:
oper_stack.pop()
elif item in "+-*/":
while oper_stack.peek() and \
priority[oper_stack.peek()] >= priority[item]:
result += oper_stack.pop()
else:
oper_stack.push(item)
while not oper_stack.is_empty():
result += oper_stack.pop()
return result
if __name__ == '__main__':
print(convert_postfix("A+B*C"))
print(convert_postfix("(A+B)*C"))
2.1.5.6 后綴表達式求值
對于后綴表達式從左到右掃描,由于操作符在操作數后面,所以要暫存操作數,在遇到操作符的時候再將暫存的兩個操作數進行實際的計算。
例如: ABC*+,先掃描到了ABC暫存到棧中,掃描到*的時候,從棧中彈出2個操作數做乘法,做完之后再存入棧中;繼續掃描到+,從棧中彈出2個操作數做加法。
注意:對于-/操作符,彈出的兩個操作數順序很重要,先彈出的是右操作數,后彈出的是左操作數。
算法流程:
import string
from data_structure.Stack.stack import Stack
from data_structure.Stack.infix_to_postfix import convert_postfix
def calculate(expression):
stack = Stack()
for item in expression:
if item in string.digits:
stack.push(item)
elif item in "+-*/":
first = stack.pop()
second = stack.pop()
stack.push(str(eval(second + item + first)))
return stack.pop()
if __name__ == '__main__':
print(calculate(convert_postfix("1+2*3")))
print(calculate(convert_postfix("(1+2)*3")))
2.2 隊列Queue
總結
以上是生活随笔為你收集整理的python 表达式求值数据结构_python 数据结构与算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 天水治免疫性不孕最好的医院推荐
- 下一篇: 梦幻模拟战索菲亚皮肤怎么获取