標籤:棧 stack 尾碼
難得有些許空閑,看一下Python的資料結構--Stack,現將幾個典型樣本進行總結!
一、什麼是棧
棧是一個有序集合,根據其特性可以稱為"先進後出"或"後進先出", 其中添加或刪除都發生在同一端,這一端被稱為"棧頂",與其對應的叫"棧底"。
棧的底部很重要,因為其底部儲存的資料是時間最長的,最近的添加項總是最先會彈出,這種排序原則有時被稱為"LIFO"
二、棧
1. 棧的可用操作
Stack() 建立一個空的新棧。 它不需要參數,並返回一個空棧。
push(item)將一個新項添加到棧的頂部。它需要 item 做參數並不返回任何內容。
pop() 從棧中刪除頂部項。它不需要參數並返回item 。棧被修改。
top() 從棧返回頂部項,但不會刪除它。不需要參數。 不修改棧。
isEmpty()測試棧是否為空白。不需要參數,並返回布爾值。
size() 返回棧中的item 數量。不需要參數,並返回一個整數。
clear 清空棧,沒有傳回值
2. 利用Python 的內建的資料結構List實現棧全部操作
class Stack(): def __init__(self): self.itmes = [] def isEmpty(self): return self.itmes == [] def clear(self): del self.itmes[:] def push(self, item): self.items.append(item) def pop(self): return self.itmes.pop() def top(self): return self.items[-1] def size(self): return len(self.itmes)
3. 棧的使用樣本
3.1 進位轉換
class Stack(): def __init__(self): self.itmes = [] def isEmpty(self): return self.itmes == [] def clear(self): del self.itmes[:] def push(self, item): self.items.append(item) def pop(self): return self.itmes.pop() def top(self): return self.items[-1] def size(self): return len(self.itmes)def divideBy2(decNumber, base): remstack = Stack() while decNumber > 0: rem = decNumber % base remstack.push(rem) decNumber = decNumber // base binString = "" while not remstack.empty(): binString = binString + str(remstack.pop()) return binStringif __name__ == ‘__main__‘: print(divideBy2(42, 2))
說明: 這是用List結構來實現的"棧", 同樣我們可以自己寫一個棧
3.2 自己寫棧
class Node: def __init__(self, value): self.value = value self.next = Noneclass Stack: def __init__(self): self.top = None def push(self, value): node = Node(value) node.next = self.top self.top = node def pop(self): node = self.top self.top = node.next return node.values = Stack()s.push(3)s.push(‘ac‘)s.push(‘er‘)s.pop()s.push(5)
說明
上面所定義的棧,是由top指標指向一個完整的Node執行個體
定義一個棧,使用指標控制其讀取的位置。
3.3 棧應用--首碼運算式(波蘭式)
from __future__ import divisionclass Node(): def __init__(self, value): self.value = value self.next = Noneclass StackNode(): def __init__(self): self.top = None def push(self, value): node = Node(value) node.next = self.top self.top = node def pop(self): node = self.top self.top = node.next return node.valuedef compute_exec(op, ov1, ov2): def add(ov1, ov2): return ov1 + ov2 def sub(ov1, ov2): return ov1 - ov2 def mul(ov1, ov2): return ov1 * ov2 def div(ov1, ov2): return ov1 / ov2 ops = {add: ‘+‘, sub: ‘-‘, mul: ‘*‘, div: "/"} for k, v in ops.items(): if v == op: ret = k(ov1, ov2) stack1.push(ret) breakdef perfix_reverse(string): # reverse tmp = ‘‘ for s in string[::-1]: if s == "(": tmp += ")" elif s == ")": tmp += "(" else: tmp += s return tmpdef infix_to_prefix(string): opt = ‘‘ string_tmp = perfix_reverse(string) for i in string_tmp: # 首碼運算式 if i.isdigit(): opt = i + opt elif i != ‘)‘: stack1.push(i) elif i == ")": opt = stack1.pop() + opt stack1.pop() for s in opt[::-1]: if s.isdigit(): stack1.push(s) else: op1 = s ov1 = stack1.pop() ov2 = stack1.pop() compute_exec(op1, int(ov1), int(ov2)) # compute result continue return opt, stack1.pop()if __name__ == ‘__main__‘: stack1 = StackNode() # 操作符 infix = [‘((3+4)*2)‘, ‘((3+(4*2))-1)‘, ‘(5*(1+2))‘] for i, v in enumerate(infix): print infix[i], "==>", infix_to_prefix(v)
說明:
首碼運算式就是說操作符位於運算元之前
運算式從右向左依次解析。將數值壓棧,遇到符號將棧頂的運算元與次位置彈出進行計算,結果再次入棧,直到運算式解析完成。
3.4 棧應用--尾碼運算式(逆波蘭式)
class Node(): def __init__(self, value): self.value = value self.next = Noneclass StackNode(): def __init__(self): self.top = None def push(self, value): node = Node(value) node.next = self.top self.top = node def pop(self): node = self.top self.top = node.next return node.valuedef compute_exec(op, ov1, ov2): def add(ov1, ov2): return ov1 + ov2 def sub(ov1, ov2): return ov1 - ov2 def mul(ov1, ov2): return ov1 * ov2 def div(ov1, ov2): return ov1 / ov2 ops = {add: ‘+‘, sub: ‘-‘, mul: ‘*‘, div: "/"} for k, v in ops.items(): if v == op: ret = k(ov1, ov2) stack1.push(ret) breakdef postfix(expr): for s in expr: if s.isdigit(): stack2.push(s) elif s != ")": stack1.push(s) elif s == ")": top = stack2.pop() snext = stack2.pop() stack2.push(‘‘.join([snext, top, stack1.pop()])) stack1.pop() post_expr = stack2.pop() for i in post_expr: if i.isdigit(): stack1.push(i) else: op = i top = stack1.pop() snext = stack1.pop() compute_exec(op, int(snext), int(top)) return post_expr, stack1.pop()if __name__ == ‘__main__‘: stack1 = StackNode() # 操作符 stack2 = StackNode() # 運算元 exprs = [‘((3+(4*2))-1)‘, ‘((3*4)+(3/2))‘] for e in exprs: print e, "==>", postfix(e)
說明:
尾碼運算式就是說操作符位於運算元之後。
運算式從左向右依次解析。將數值壓棧,遇到符號將棧頂的運算元與次位置彈出進行計算[次位運算元 棧頂運算元 操作符 ],結果再次入棧,直到運算式解析完成
計算運算式結果時同樣是[次位運算元 操作符 棧頂運算元 ]
四、總結
以上樣本都可以通過http://pythontutor.com/visualize.html#mode=edit 查看程式啟動並執行每一步
本文參考於https://www.gitbook.com/book/facert/python-data-structure-cn/details
以上後兩個範例程式碼基於自己理解所寫,可能存在bug
後兩個樣本的缺點是沒有寫運算式合法性的檢查,運算式的優先順序(如運算式無括弧可能會導致程式異常)
此處僅是對棧的一此粗淺理解及應用。
本文出自 “和風細雨” 部落格,請務必保留此出處http://essun.blog.51cto.com/721033/1941041
資料結構[Python--Stack] 的應用