Java 集合深入理解(9):Queue 佇列
阿新 • • 發佈:2019-01-05
今天心情不太好,來學一下 List 吧!
什麼是佇列
佇列是資料結構中比較重要的一種型別,它支援 FIFO,尾部新增、頭部刪除(先進佇列的元素先出佇列),跟我們生活中的排隊類似。
佇列有兩種:
- 單佇列
- 迴圈佇列
單佇列就是常見的佇列, 每次新增元素時,都是新增到隊尾:
以陣列實現的佇列為例,初始時佇列長度固定為 4,font 和 rear 均為 0:
每新增一個元素,rear 後移一位。當新增四個元素後, rear 到了索引為 4 的位置:
這時 a1,a2 出隊,front 後移動到 2:
這時想要再新增兩個元素,但 rear 後移兩位後就會越界:
明明有三個空位,卻只能再放入一個!這就是單佇列的“假溢位”情況。
針對這種情況,解決辦法就是後面滿了,就再從頭開始,也就是頭尾相接的迴圈。這就是 “迴圈佇列” 的概念。
迴圈佇列:
迴圈佇列中,
rear = (rear - size) % size
接著上面的例子,當 rear 大於 佇列長度時,rear = ( 5 - 5) % 5 = 0 :
這樣繼續新增時,還可以新增幾個元素:
那如何判斷佇列是否裝滿元素了呢,單使用 front == rear 無法判斷究竟是空的還是滿了。
兩種方法:
- 加個標誌 flag ,初始為 false,新增滿了置為 true;
- 不以 front = rear 為放滿標誌,改為 (rear - front) % size = 1。
法 2 的公式放滿元素時空餘了一個位置,這個公式是什麼意思呢?
接著上面的情況,當 rear 從後面新增元素跑到前面 0 時,再新增一個元素 a6,rear 後移一位到 1,這時 front = 2, (1 - 2) % 5 = 1, 滿足放滿條件。
因此,當 rear > font 時,佇列中元素個數 = rear - font;
當 rear < font 時,佇列中元素分為兩部分: size - font 和 rear ,也就是 rear + size - font。以上述圖片為例,佇列中元素個數 = 1 + 5 - 2 = 4.
接著我們介紹 Java 集合框架中的佇列 Queue
Java 集合中的 Queue 繼承自 Collection 介面 ,Deque, LinkedList, PriorityQueue, BlockingQueue 等類都實現了它。
Queue 用來存放 等待處理元素 的集合,這種場景一般用於緩衝、併發訪問。
除了繼承 Collection 介面的一些方法,Queue 還添加了額外的 新增、刪除、查詢操作。
新增、刪除、查詢這些個操作都提供了兩種形式,其中一種在操作失敗時直接丟擲異常,而另一種則返回一個特殊的值:
Queue 方法介紹:
1.add(E), offer(E) 在尾部新增:
boolean add(E e);
boolean offer(E e);
他們的共同之處是建議實現類禁止新增 null 元素,否則會報空指標 NullPointerException;
不同之處在於 add() 方法在新增失敗(比如佇列已滿)時會報 一些執行時錯誤 錯;而 offer() 方法即使在新增失敗時也不會奔潰,只會返回 false。
2016.11.21 新增
注意
Queue 是個介面,它提供的 add, offer 方法初衷是希望子類能夠禁止新增元素為 null,這樣可以避免在查詢時返回 null 究竟是正確還是錯誤。
事實上大多數 Queue 的實現類的確響應了 Queue 介面的規定,比如 ArrayBlockingQueue,PriorityBlockingQueue 等等。
但還是有一些實現類沒有這樣要求,比如 LinkedList。
2.remove(), poll() 刪除並返回頭部:
E remove();
E poll();
當佇列為空時 remove() 方法會報 NoSuchElementException 錯; 而 poll() 不會奔潰,只會返回 null。
3.element(), peek() 獲取但不刪除:
E element();
E peek();