棧與隊列
棧
棧的是一種線性結構,棧存儲數據類似於乒乓球筒中放入或取出乒乓球的過程,遵從先進后出的原則。
棧相比於同樣是線性結構的順序表,關閉了部分接口,提高程序的穩定性。
用Python實現棧
- Stack()創建一個新的空棧
- push(item)添加一個新的元素item到棧頂
- pop()彈出棧頂元素
- peek()返回棧頂元素
- is_empty()判斷棧是否為空
- size()返回棧的元素個數
- tracel()輸出棧中所以元素
class Stack:
def __init__(self):
self.__data = []
def is_empty(self):
"""判斷棧是否為空"""
return self.__data == []
def push(self, data):
"""在棧頂添加元素"""
self.__data.append(data)
def pop(self):
"""彈出頂部元素"""
return self.__data.pop()
def peek(self):
"""返回棧頂元素"""
# 先判斷是否為空
if self.is_empty():
return
else:
return self.__data[-1]
def size(self):
"""判斷長度"""
return len(self.__data)
def travel(self):
"""遍歷所有元素"""
self.__data = self.__data[::-1]
for i in self.__data:
print(i)
if __name__ == '__main__':
a = Stack()
print(a.is_empty())
a.push(0)
a.push(1)
a.push(2)
a.push(3)
a.travel()
使用Python中的列表,我們可以輕松的創建一個棧,棧在程序中用處是較多的一種結構,我們瀏覽器的前進后推中就用到了棧
瀏覽器中用到的棧
當我們沒次訪問一個新頁面,瀏覽器就會已棧的結構記下一條我們的瀏覽記錄。之后如果我們需要返回,瀏覽器就會輸出棧頂數據,也就是我們最后訪問的那個頁面。並同時將棧頂元素存檔在另一個棧中,一共后續前進使用。
if __name__ == '__main__':
prev = Stack()
next = Stack()
i = 1
while True:
print('按1為點擊新頁面,2為返回,3為前進')
a = int(input('請輸入數字: '))
if a == 1:
prev.push(f'第{i}個頁面')
print(f'當前在{prev.peek()}')
i += 1
elif a == 2:
if prev.is_empty():
print('不存在上個頁面')
elif prev.size() == 1:
print('首頁無法返回')
else:
next.push(prev.pop())
print(f'當前在{prev.peek()}')
elif a == 3:
if next.is_empty():
print('不存在下個頁面')
else:
prev.push(next.pop())
print(f'當前在{prev.peek()}')
隊列
隊列遵循的是后出原則,隊列和棧都是受限制的線性表結構,隊列相較於棧更好理解,因為平時我們都或多或少經歷過排隊。而且隊列的使用也相當多,比如說並發隊列,循環隊列,阻塞隊列,在系統底層、框架、中間件的開發中,起着關鍵性作用。
## 用Python實現隊列
class Queue:
def __init__(self):
self.__data = []
def enqueue(self, data):
"""往隊列頭中添加一個新元素"""
self.__data.insert(0, data)
def travel(self):
"""遍歷所有元素"""
for i in self.__data:
print(i, end='')
print('')
def dequeue(self):
"""從隊列尾刪除一個元素"""
self.__data.pop()
def is_empty(self):
"""判斷隊列是否為空"""
return self.__data == []
def size(self):
"""返回隊列的元素個數"""
return len(self.__data)
隊列和棧在代碼是現實上非常相似,都可以算是一種受到限制的順序表
雙端隊列
雙端隊列可在隊列任意一側出隊入隊。
雙端隊列只需加入對頭的出隊和隊尾入隊的方式即可
def appqueue(self, data):
"""在隊尾添加新元素"""
self.__data.append(data)
def delqueue(self):
"""刪除對頭元素"""
self.__data.pop(0)
擴展
我們發現棧和隊列中有大量相同的方法,我們可以使用繼承和封裝來優化代碼
# 利用繼承寫棧與隊列
class Repeat:
def __init__(self):
self.__data = []
def is_empty(self):
"""判斷是否為空"""
return self.__data == []
def push(self, data):
"""頭部添加元素"""
self.__data.insert(0, data)
def travel(self):
"""遍歷所有元素"""
for i in self.__data:
print(i)
print('')
def size(self):
"""返回隊列的元素個數"""
return len(self.__data)
@property
def data(self):
return self.__data
@data.setter
def data(self, n):
self.__data = n
class Stack(Repeat):
def pop(self):
"""彈出頂部元素"""
return self.data.pop(0)
def peek(self):
"""返回棧頂元素"""
# 先判斷是否為空
if self.is_empty():
return False
else:
return self.data[0]
class Queue(Repeat):
def pop(self):
"""隊尾元素出隊"""
return self.data.pop()