1. 程式人生 > >棧:概念與實現

棧:概念與實現

棧(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