棧(Stack)在計算機領域是一個被廣泛應用的集合,棧是線性集合,訪問都嚴格地限制在一段,叫做頂(top)。 舉個例子,棧就想一摞洗乾淨的盤子,你每次取一個新盤子,都是放在這一摞盤子的最上頭,當你往裡面新增盤子的時候,也是放在最上面,處在底部的盤子,你可能永遠也用不到。 棧的最常見操作,有如下兩個:
push(a) # 壓入,將a壓入的棧中
pop() # 彈出,將棧的最後一個元素彈出
複製程式碼
可是使用Python的列表資料結構,來模擬棧的操作,使用append
來模擬push
,使用列表的pop
來模擬棧的pop
,但是這樣做有一個弊端,那就是列表原本自帶的操作方法同樣能夠使用,可能會造成混亂。
- 棧的實現 下面就通過藉助Python的列表,來自定義一個棧類:
class Stack(object):
"""使用陣列實現一個棧"""
def __init__(self):
self.data = []
def push(self, num):
"""壓棧操作"""
self.data.append(num)
def pop(self):
"""返回從棧中彈出的元素, 當棧為空的時候, 丟擲IndexError"""
return self.data.pop()
def peek(self):
"""檢視當前棧頂的元素, 當棧為空的時候, 丟擲IndexError"""
return self.data[-1]
def __len__(self):
"""返回棧的長度, 呼叫len(obj)時會自動呼叫obj物件的__len__方法"""
return len(self.data)
def isEmpty(self):
"""判斷棧是否為空"""
return True if len(self.data)==0 else False
def clear(self):
"""清空棧"""
self.data = []
def __repr__(self):
"""當前物件的表現形式, 在終點直接鍵入物件時會呼叫"""
return 'Stack_' + str(self.data)
def __str__(self):
"""當前物件的字串表示, 使用print(obj)時會呼叫"""
return 'Stack_' + str(self.data)
複製程式碼
以上程式碼實現了一個簡單的基於列表的棧。
- 棧的應用
棧應用的一個很典型的例子,就是檢查括號是否匹配。
例如: 每一個開始的
[
後面,都應該跟著一個位置正確的]
,並且每一個(
後面,也應該跟著一個位置正確的結束的)
.
(...)...(...)
匹配(...)...(...
不匹配)...((...)
不匹配 像第三個示例中,雖然左右括號的數量是相等的,但是也是不匹配的,所以不能通過簡單的檢查數量來實現括號的檢測。 一種非常有效的解決方式就是使用棧:- 掃描整個字串, 如果遇到一個開始的括號,將它壓入到棧中
- 如果遇到一個結束的括號,檢查棧頂的元素,如果是結束的括號,就將當前括號壓入棧中,如果是開始的括號,檢查與當前括號是否能配對,不能配對則不匹配
- 如果遇到一個結束的括號,並且當前棧為空的話,那麼也是不匹配的。 程式碼實現如下:
def isBalance(text):
"""棧的應用,檢查括號是否平衡"""
result_stack = Stack()
for i in text:
if i in ['{', '[', '(']:
result_stack.push(i)
elif i in ['}', ']', ')']:
# 遇到結束括號的情況
if result_stack.isEmpty():
# 如果當前棧為空, 不匹配,返回False
return False
chFromStack = result_stack.pop()
if not ((chFromStack == '{' and i == '}' )
or (chFromStack == '[' and i == ']')
or (chFromStack == '(' and i == ')')):
# 如果不滿足匹配條件, 則返回False
return False
# 遍歷結束後, 如果結果棧為空, 則代表括號匹配, 棧不為空, 括號不匹配
return result_stack.isEmpty()
複製程式碼