資料結構與演算法—棧和佇列
阿新 • • 發佈:2020-10-26
1. 棧
棧(stack),有些地方稱為堆疊,是一種容器,可存入資料元素、訪問元素、刪除元素,它的特點在於只能允許在容器的一端(稱為棧頂端指標,英語:top)進行加入資料(英語:push)和輸出資料(英語:pop)的運算。沒有了位置概念,保證任何時候可以訪問、刪除的元素都是此前最後存入的那個元素,確定了一種預設的訪問順序。
由於棧資料結構只允許在一端進行操作,因而按照後進先出(LIFO, Last In First Out)的原理運作。
棧可以用順序表實現,也可以用連結串列實現。
(1)棧的操作
- Stack() 建立一個新的空棧
- push(item) 新增一個新的元素item到棧頂
- pop() 彈出棧頂元素
- peek() 返回棧頂元素
- is_empty() 判斷棧是否為空
- size() 返回棧的元素個數
(2)棧的實現
class Stack(object): """建立一個新的空棧""" def __init__(self): # 棧可以用順序表或連結串列實現,同時需要考慮以哪一端作為棧頂。 # 從時間複雜度上考慮,List以列表尾部作為棧頂較合適,入棧出棧複雜度為o(1),連結串列以頭部作為棧頂較合適,入棧出棧複雜度為o(1) # 這裡使用順序表 self.list = [] def is_empty(self): """判斷棧是否為空""" return self.list == [] # return not self.list def push(self, item): """新增一個新的元素item到棧頂""" self.list.append(item) def pop(self): """彈出棧頂元素""" return self.list.pop() def peek(self): """返回棧頂元素""" if self.is_empty(): return None else: return self.list[-1] def size(self): """返回棧的元素個數""" return len(self.list) if __name__ == "__main__": stack = Stack() stack.push("hello") stack.push("world") stack.push("itcast") print (stack.size()) print (stack.peek()) print (stack.pop()) print (stack.pop()) print (stack.pop())
3
itcast
itcast
world
hello
2. 佇列
佇列(queue)是隻允許在一端進行插入操作,而在另一端進行刪除操作的線性表。
佇列是一種先進先出的(First In First Out)的線性表,簡稱FIFO。允許插入的一端為隊尾,允許刪除的一端為隊頭。佇列不允許在中間部位進行操作!假設佇列是q=(a1,a2,……,an),那麼a1就是隊頭元素,而an是隊尾元素。這樣我們就可以刪除時,總是從a1開始,而插入時,總是在佇列最後。這也比較符合我們通常生活中的習慣,排在第一個的優先出列,最後來的當然排在隊伍最後。
同棧一樣,佇列也可以用順序表或者連結串列實現。
(1)佇列的操作
- Queue() 建立一個空的佇列
- enqueue(item) 往佇列中新增一個item元素
- dequeue() 從佇列頭部刪除一個元素
- is_empty() 判斷一個佇列是否為空
- size() 返回佇列的大小
(2)佇列的實現
class Queue(object):
"""建立一個空的佇列"""
def __init__(self):
self.list = []
def enqueue(self, item):
"""往佇列中新增一個item元素"""
# 列表要先確定哪裡是佇列頭,佇列尾。
# 如果列表尾部為佇列尾,則複雜度入佇列為o(1),出佇列為o(n);若列表頭部為佇列尾,則複雜度是相反的。
# 因此需要根據具體情況,看是入隊還是出隊使用更頻繁來決定
self.list.append(item) # 列表尾部為佇列尾
# self.list.insert(0,item) # 列表頭部為佇列尾
def dequeue(self):
"""從佇列頭部刪除一個元素"""
return self.list.pop(0) # 在列表頭部彈出
# return self.list.pop() # 在列表尾部彈出
def is_empty(self):
"""判斷一個佇列是否為空"""
return self.list == []
def size(self):
"""返回佇列的大小"""
return len(self.list)
if __name__ == "__main__":
q = Queue()
q.enqueue("hello")
q.enqueue("world")
q.enqueue("itcast")
print (q.size())
print (q.dequeue())
print (q.dequeue())
print (q.dequeue())
3
hello
world
itcast
3.雙端佇列
雙端佇列(deque,全名double-ended queue),是一種具有佇列和棧的性質的資料結構。
雙端佇列中的元素可以從兩端彈出,其限定插入和刪除操作在表的兩端進行。雙端佇列可以在佇列任意一端入隊和出隊。
(1)雙端佇列的操作
- Deque() 建立一個空的雙端佇列
- add_front(item) 從隊頭加入一個item元素
- add_rear(item) 從隊尾加入一個item元素
- remove_front() 從隊頭刪除一個item元素
- remove_rear() 從隊尾刪除一個item元素
- is_empty() 判斷雙端佇列是否為空
- size() 返回佇列的大小
(2) 雙端佇列的實現
class Deque(object):
"""建立一個空的雙端佇列"""
def __init__(self):
self.list = []
def add_front(self, item):
"""從隊頭加入一個item元素"""
self.list.insert(0,item)
def add_rear(self, item):
"""從隊尾加入一個item元素"""
self.list.append(item)
def remove_front(self):
"""從隊頭刪除一個item元素"""
return self.list.pop(0)
def remove_rear(self):
"""從隊尾刪除一個item元素"""
return self.list.pop()
def is_empty(self):
"""判斷雙端佇列是否為空"""
return self.list == []
def size(self):
"""返回佇列的大小"""
return len(self.list)
if __name__ == "__main__":
deque = Deque()
deque.add_front(1)
deque.add_front(2)
deque.add_rear(3)
deque.add_rear(4)
print (deque.size())
print (deque.remove_front())
print (deque.remove_front())
print (deque.remove_rear())
print (deque.remove_rear())
4
2
1
4
3