数据结构与算法笔记(五)——队列(FIFO队列、双端队列)
一、FIFO隊列
1.1、概念
隊列(queue)是只允許在一端進行插入操作,而在另一端進行刪除操作的線性表。
隊列是一種先進先出的(First In First Out)的線性表,簡稱FIFO。允許插入的一端為隊尾,允許刪除的一端為隊頭。隊列不允許在中間部位進行操作!假設隊列是q= (a1,a2,…,an),那么a1就是隊頭元素,而an是隊尾元素。這樣我們就可以刪除時,總是從a1開始,而插入時,總是在隊列最后。這也比較符合我們通常生活中的習慣,排在第一個的優先出列,最后來的當然排在隊伍最后。
1.2、隊列操作及實現
同棧一樣,隊列也可以用順序表或者鏈表實現。
(事實上,python自帶queue模塊,這里還是自己實現下)
操作:
- Queue():創建一個空的隊列
- enqueue(item):往隊列中添加一個item元素
- dequeue():從隊列頭部刪除一個元素
- is_empty():判斷一個隊列是否為空
- size():返回隊列的大小
實現:
class Qeque(object):"""隊列"""def __init__(self):self.__list = []def is_empty(self):"""判斷隊列是否為空"""return self.__list == []def size(self):"""返回隊列大小"""return len(self.__list)def enqueue(self, item):"""往隊列中添加一個item元素"""self.__list.append(item)def dequeue(self):"""從隊列頭部刪除一個元素"""return self.__list.pop(0)if __name__ == '__main__':q =Qeque()q.enqueue(1)q.enqueue(2)q.enqueue(3)q.enqueue(4)print(q.dequeue(),end=' ')print(q.dequeue(),end=' ')print(q.dequeue(),end=' ')print(q.dequeue(),end=' ')二、雙端隊列
2.1、概念
雙端隊列(deque,全名double-ended queue),是一種具有隊列和棧的性質的數據結構。
雙端隊列中的元素可以從兩端彈出,其限定插入和刪除操作在表的兩端進行。雙端隊列可以在隊列任意一端入隊和出隊。
2.2、雙端隊列操作及實現
操作:
- Deque():創建一個空的雙端隊列
- add_front(item):從隊頭加入一個item元素
- add_rear(item):從隊尾加入一個item元素
- remove_front():從隊頭刪除一個item元素
- remove_rear():從隊尾刪除一個item元素
- is_empty():判斷雙端隊列是否為空
- size():返回隊列的大小
實現:
class Deque(object):"""雙端隊列"""def __init__(self):self.__list = []def is_empty(self):"""判斷隊列是否為空"""return self.__list == []def size(self):"""返回隊列大小"""return len(self.__list)def add_front(self, item):"""在隊頭添加一個元素"""self.__list.insert(0, item)def add_rear(self, item):"""在隊尾添加元素"""self.__list.append(item)def remove_front(self):"""從隊頭刪除元素"""return self.__list.pop(0)def remove_rear(self):"""從隊尾刪除元素"""return self.__list.pop()三、python模塊Queue
Queue是python標準庫中的線程安全的隊列(FIFO)實現,提供了一個適用于多線程編程的先進先出的數據結構,即隊列,用來在生產者和消費者線程之間的信息傳遞。
3.1、創建隊列對象
import queue myqueue = queue.Queue(maxsize = 10)Queue.Queue類即是一個隊列的同步實現。隊列長度可為無限或者有限。可通過Queue的構造函數的可選參數maxsize來設定隊列長度。如果maxsize小于1就表示隊列長度無限。
3.2、常用方法
- Queue.qsize() 返回隊列的大小
- Queue.empty() 如果隊列為空,返回True,反之False
- Queue.full() 如果隊列滿了,返回True,反之False,Queue.full 與 maxsize 大小對應
- Queue.get() 從隊列中取最后一個數據
- Queue.get_nowait() 相當于Queue.get(False),非阻塞方法
- Queue.put(item) 寫入隊列,timeout等待時間
- Queue.task_done() 在完成一項工作之后,Queue.task_done()函數向任務已經完成的隊列發送一個信號。每個get()調用得到一個任務,接下來- -task_done()調用告訴隊列該任務已經處理完畢。
- Queue.join() 實際上意味著等到隊列為空,再執行別的操作
3.3、案例:生產者消費者模式開發的Python多線程
在Python中,隊列是最常用的線程間的通信方法,因為它是線程安全的,自帶鎖。而Condition等需要額外加鎖的代碼操作,在編程對死鎖現象要很小心,Queue就不用擔心這個問題。
Queue多線程代碼示例如下:
from queue import Queue import time, threadingq = Queue(maxsize=0)def product(name):count = 1while True:q.put('商品{}'.format(count))print('{}生產商品{}個'.format(name, count))count += 1time.sleep(5)def consume(name):while True:print('{}消費{}個'.format(name, q.get()))time.sleep(2)q.task_done()t1 = threading.Thread(target=product, args=('python',)) t2 = threading.Thread(target=consume, args=('java',))t1.start() t2.start()結果:
python生產商品1個 java消費商品1個 python生產商品2個 java消費商品2個 ·······3.4、queue模塊其他隊列
queue模塊有三種隊列:
針對這三種隊列分別有三個構造函數:
示例
from queue import Queue, LifoQueue, PriorityQueue# 先進先出隊列 q = Queue(maxsize=5) # 后進先出隊列 lq = LifoQueue(maxsize=6) # 優先級隊列 pq = PriorityQueue(maxsize=5)for i in range(5):q.put(i)lq.put(i)pq.put(i)print("先進先出隊列:%s;是否為空:%s;多大,%s;是否滿,%s" % (q.queue, q.empty(), q.qsize(), q.full())) print("后進先出隊列:%s;是否為空:%s;多大,%s;是否滿,%s" % (lq.queue, lq.empty(), lq.qsize(), lq.full())) print("優先級隊列:%s;是否為空:%s,多大,%s;是否滿,%s" % (pq.queue, pq.empty(), pq.qsize(), pq.full()))print(q.get(), lq.get(), pq.get())結果:
先進先出隊列:deque([0, 1, 2, 3, 4]);是否為空:False;多大,5;是否滿,True 后進先出隊列:[0, 1, 2, 3, 4];是否為空:False;多大,5;是否滿,False 優先級隊列:[0, 1, 2, 3, 4];是否為空:False,多大,5;是否滿,True 0 4 0總結
以上是生活随笔為你收集整理的数据结构与算法笔记(五)——队列(FIFO队列、双端队列)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构与算法笔记(四)—— 栈
- 下一篇: 数据结构与算法笔记 —— 十大经典排序及