數據結構[Python--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 binString if __name__ == ‘__main__‘: print(divideBy2(42, 2))
說明: 這是用List結構來實現的"棧", 同樣我們可以自己寫一個棧
3.2 自己寫棧
class Node: def __init__(self, value): self.value = value self.next = None class 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.value s = Stack() s.push(3) s.push(‘ac‘) s.push(‘er‘) s.pop() s.push(5)
說明
上面所定義的棧,是由top指針指向一個完整的Node實例
定義一個棧,使用指針控制其讀取的位置。
3.3 棧應用--前綴表達式(波蘭式)
from __future__ import division class Node(): def __init__(self, value): self.value = value self.next = None class 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.value def 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) break def perfix_reverse(string): # reverse tmp = ‘‘ for s in string[::-1]: if s == "(": tmp += ")" elif s == ")": tmp += "(" else: tmp += s return tmp def 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 = None class 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.value def 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) break def 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] 的應用