棧:概念與實現
阿新 • • 發佈:2018-12-16
棧(stack)是一種容器,可存入資料元素,訪問元素,刪除元素等。存入棧中的元素之間相互沒有任何具體聯絡,只有到來的先後順序。 棧可以實現為在一端進行插入和刪除的線性表,因此也稱為後進先出表(LIFO) 在表實現中,執行插入和刪除一端的操作稱為棧頂,另一端稱為棧底。訪問和彈出的都應該顯是棧頂元素。
- 對於順序表,後端插入和刪除是O(1)時間操作,應該用後端作為棧頂
- 對於連結表,前端插入和刪除都是O(1)時間操作,應該用前端作為棧頂
1 棧的順序表實現
- 建立空棧對應於建立一個空表 [] ,判斷空棧對應於檢查是否為空表
- 由於list 採用動態順序表技術(分離式實現),作為棧的表不會滿
- 壓入元素在表單尾端進行,對應於lst.append(x)
- 訪問棧頂元素應該用 list[-1]
- 彈出元素操作也應該在表單尾端進行,無引數的lst.pop()預設彈出表尾元素
這裡把list 當做棧使用,完全可以滿足應用的需要。但是這樣的物件還是list,提供了list 型別的所有操作,
特別是提供了一大批棧結構原來不應該支援的操作,威脅安全性
例如:棧要求未經彈出的元素應該存在,但是表允許刪除。
現在考慮基於順序表定義一個棧類,使之成為一個獨立的型別,把Python 的list隱藏在這個類的內部,作為其實現基礎。 下面是一個棧類的定義,其中用一個list型別的資料屬性_elems作為棧元素儲存區,用_elems的首端作為棧底,尾端作為棧頂
class SStack(): # 基於順序表實現的棧類 def __init__(self): # 用list物件_elems儲存棧中元素 self._elems = [ ] # 所有棧操作都對映到棧操作 def is_empty(self): return self._elems == [ ] def top(self): if self._elems == [ ]: raise StackUnderflow( 'in stack.top()' ) else: return self._elems[-1] def push(self, elem): self._elems.append(elem) def pop(self): if self._elems == []: rasie StacakUnderflow(' in stack.pop()') else: return self._elems.pop()
以上程式碼都是基於Python 的list實現,所有理解起來不是很難
2 棧的連結表實現
使用順序表實現棧,還是有些缺點,比如當list的元素儲存區滿了以後,要擴大元素儲存區是一次高代價操作,而且,順序表還需要完整的大的儲存區。連結表的實現在這兩個問題上都有優勢。 當然,連結表的缺點是更多的依賴是直譯器的儲存管理,每個節點的連結開銷,以及連結結點在實際計算機記憶體中任意散步可能帶來的操作開銷。 採用連結表技術,自然用表頭一端作為棧頂,表尾作為棧底
class LStack(): # 基於連結表技術實現的棧類,用LNode作為結點 def __init__(self): self._top = None def is_empty(self): return self._top is None def top(self): if self._top is None: raise StackUnderflow('in LStack.top()') else: return self._top.elem def push(self, elem): # 入棧->連結表->插入首端->新元素成為首元素 # 此時self._top 等於新的元素 self._top = LNode(elem, self._top) def pop(self): if self._top is None: raise StackUnderflow("in LStack.pop()") p = self._top # 移除第一個元素,此時首元素為原先的第二個 self._top = p.next return p.elem