前言
- 有Python基礎
- 有數據結構的基礎的話那當然是再好不過了
原理
先進後出
- 初始化時,棧爲空。
- 數據入棧時,第一個數據先進到棧底,此時棧頂也是這個元素(因爲目前棧中只有一個元素)。第二個數據入棧,則處於棧頂,即在第一個元素的上面。後續加入的情況亦是如此,第三個在第二個的上面,第四個在第三個的上面…當然以上情況僅考慮入棧,中間不曾出棧。新的元素加入後都是處在當時情況下的棧頂。
- 出棧時,棧頂的元素先出。比如上圖,棧頂的e(n-1)先出,之後e(n-2)才能出…最後,底層元素e(0)才能出棧。當然,這裏也是僅考慮出棧的情況。動的元素照樣是棧頂元素。
- 因此,棧只對棧頂元素進行操作。
- 一般考試的時候或者筆試的時候不會單純地出只有入棧或者出棧的情況,一般會綜合起來考察。可能會出這樣的題,給定一組序列,比如1,2,…,10,期間可以有入棧和出棧,讓你從選項中選出不可能出現的情況。比如下面的這道題(來自某度文庫)。
實現
環境
Python3.7 + win10 + pycharm。重點是Python3,其他的事實上無所謂。
分析
- 在Python中選用類的方式來定義。注:在C/C++中用的比較多的是struct,當然,在C++中類的方式也是可以,關於struct和class的區別有興趣的自己搜下,這個是C/C++的內容。
- 按照上面講的初始化的時候棧是空的,因此在class Stack的構造函數中將屬性items設置爲空list。init這一塊就是構造函數,不清楚的建議補下Python基礎。
- 這裏爲什麼選用list?棧可以存不少數據吧?那需要選個可以存很多數據的數據類型吧?用字典吧…還要鍵值對,麻煩。用set吧,emmm,set裏面的元素是無序的,而且沒有重複的元素,看看棧的元素,有序吧,有重複的元素吧?因此也不適用。tuple只讀,也不合適。看來看去還是list最適合了。而且操作也方便是吧?
初始化
# 類的初始化
class Stack(object):
def __init__(self):
self.items = []
判空
初始化完之後看下其他的操作,一般來說都會有判空的操作,因此需要定義一個isEmpty的方法。原理也很簡單,當items長度是0 的時候就是空的,return True即可。否則返回False。
def isEmpty(self):
return len(self.items) == 0
入棧
接下來說下入棧的方法。進來的數據是要加到items裏面的,items是一個list,可以用append方法加入,append是把元素加到list的末尾,因此可以用items的尾部元素當做棧頂。當然,頭部那就是底部了。這裏是進行操作,可以沒有返回值,由於是加入元素,因此需要有一個參數item,將要加入的元素帶入item即可。
# 入棧
def push(self, item):
self.items.append(item)
出棧
依舊是對棧頂元素操作,將棧頂元素從items當中剔除即可,很容易想到list可以用pop()
# 刪除棧頂元素(出棧)
def remove(self):
self.items.pop()
size
如若想知道大小,那麼可以定義一個size方法,直接返回現在items的長度即可
def size(self):
return len(self.items)
遍歷
此外還可以設計一個遍歷的方法,以便於打印輸出看效果。下面travel函數這麼寫是爲了打印更好看點。
def travel(self):
for i in self.items:
print(i, end=' ')
print('')
取棧頂元素
如若是在C/C++裏面,有可能會考慮棧滿的情況,但是在Python中就沒有什麼必要了,list自己會擴張,用不着擔心滿的情況。在C裏面,items用的一般是規定大小的數組,因此會有判滿的操作。有的可能還會有取棧頂元素的操作。那可以實現下。直接讀取items的最後一個元素即可。最後一個元素的下標是len(items) - 1,好寫吧?
def get_top(self):
return self.items[len(self.items) - 1]
完整代碼
- ok ,大致的方法有這些,寫完之後需要加點東西測試一下。完整代碼如下:
class Stack(object):
def __init__(self):
self.items = []
def isEmpty(self):
return len(self.items) == 0
# 棧的特點是先進後出,操作的都是棧頂元素
# 先定義入棧的方法
# self.items是一個list,利用append方法可以將加進來的item加到列表的末尾,items的末尾相當於棧頂,items的頭部就當做棧的底部
def push(self, item):
self.items.append(item)
# 刪除棧頂元素
def remove(self):
self.items.pop()
def travel(self):
for i in self.items:
print(i, end=' ')
print('')
def get_top(self):
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
st = Stack()
print(st.isEmpty()) # 剛初始化,應該是空棧,應return True
for i in range(5):
st.push(i) # 將 0-4幾個數加入,此時size應爲5
st.travel() # 遍歷打印出來
st.remove() # 刪除棧頂元素,size應爲4
st.travel()
print(st.size()) # 預期結果4
print(st.get_top()) # 之前的棧頂元素4彈出去了,現在3是老大(棧頂),應打印3
- 結果