看過筆者前兩篇介紹的Java版
數據結構數組
和棧
的盆友,都給予了筆者一致的好評,在這裏筆者感謝你們的承認!!!前端
因爲本章介紹的數據結構是隊列
,在隊列的實現上會基於前面寫的動態數組
來實現,而隊列
又和棧
不管是從特色上和操做上都有相似之處,因此在這裏對這兩種數據結構不瞭解的朋友,能夠去看一下筆者前兩篇文章介紹的數據結構數組
和棧
,這裏筆者把連接貼出來(看過的盆友能夠跳過此步驟...)java
隊列是一種特殊的線性表,它只容許在表的前端(front)進行刪除操做,而在表的後端(rear)進行插入操做,和棧同樣,隊列是一種操做受限制的線性表。進行插入操做的端稱爲隊尾,進行刪除操做的端稱爲隊頭。git
隊列的操做方式和棧
相似,惟一的區別在於隊列只容許新數據在後端(rear)進行添加。github
以前在介紹棧的時候,經過示意圖來幫助你們瞭解什麼是棧;這裏,我仍採用示意圖形式向你們演示隊列經常使用的兩個操做:入隊操做
和出隊操做
。後端
隊列入隊操做數組
這裏咱們能夠形象地想成咱們到銀行辦理業務排隊的場景,如今A、B、C三個元素分別到銀行櫃檯排成一條隊辦理業務(咱們都是文明的孩紙,總不能插隊O(∩_∩)O哈!),依次排隊的元素是:A、B、C。數據結構
隊列出隊操做ide
當元素A
辦理完業務時,當前是元素A
先離開隊列,而後是元素B
,最後是元素C
性能
咱們時刻要牢記隊列,入隊是從
隊尾
一端進行入隊,出隊是從隊首
一端進行出隊,是一種:先進先出的數據結構。測試
本文會介紹隊列的兩張實現方式,一種是數組隊列,另一種是循環隊列,考慮篇幅長度緣由,本篇咱們暫時只介紹數組隊列,循環隊列放在下一篇介紹。
如今咱們聲明一個數組的長度(capacity=3),元素個數爲(size=0)的int類型數組的空隊列,在這裏,假設對隊列的隊首
爲數組的左側
,隊尾
爲數組的右側
,示意圖以下:
如今若是咱們有四個元素:A、B、C、D要入隊
元素A
入隊
元素A
已經入隊了,如今開始元素B
入隊
元素A
和元素B
已經入隊了,如今開始元素C
入隊
元素A
、B
和C
已經分別入隊了,如今若是咱們要開始元素D
入隊,根據咱們以前定義的動態數組的特性,若是元素D
進行入隊操做,會發現此時咱們的數組已經滿了,這時候數組會自動地擴容
(擴容的原理:新建一個容量是原數組容量兩倍的數組,把原數組中的元素依次拷貝到新的數組中,最後引用指向新的數組)的原來的兩倍(具體擴容多少,盆友能夠自行設置)示意圖以下:
到這裏咱們已經完成了元素:A、B、C、D的入隊操做了,如今咱們來看一下,它們的出隊操做,根據隊列的特性,隊列是一種先進先出
的數據結構,以前入隊操做順序依次是:A->B->C->D
,那麼出隊操做順序仍然是:A->B->C->D
如今咱們來看一下元素A
和元素B
出隊後的示意圖:
元素C
和D
的出隊原理和元素A
出隊的原理同樣,直至所有出隊完成,變成空隊列
在元素出隊的過程當中,相應地也會進行縮容操做,以前筆者這邊定義,當數組中元素的個數(size)等於數組容量(capacity)的一半時,數組會進行縮容操做,這也正是動態數組的特色。
瞭解了數組隊列的底層原理以後,接下來咱們用代碼來實現一下(建議盆友,在看以前,本身能夠嘗試寫一下,而後在看,這樣印象可能會比較深入O(∩_∩)O哈!)
void enqueue(E e);
複製代碼
E dequeue();
複製代碼
E getFront();
複製代碼
int getSize();
複製代碼
boolean isEmpty();
複製代碼
接口定義 :Queue
public interface Queue<E> {
/** * 入隊 * * @param e */
void enqueue(E e);
/** * 出隊 * * @return */
E dequeue();
/** * 獲取隊首元素 * * @return */
E getFront();
/** * 獲取隊列中元素的個數 * * @return */
int getSize();
/** * 判斷隊列是否爲空 * * @return */
boolean isEmpty();
}
複製代碼
DynamicArrayQueue 類實現接口 Queue
public class DynamicArrayQueue<E> implements Queue<E> {
/** * 用數組存放隊列中元素的個數 */
private DynamicArray<E> dynamicArray;
/** * 指定容量,初始化隊列 * * @param capacity */
public DynamicArrayQueue(int capacity) {
dynamicArray = new DynamicArray<>(capacity);
}
/** * 默認容量,初始化隊列 */
public DynamicArrayQueue() {
dynamicArray = new DynamicArray<>();
}
@Override
public void enqueue(E e) {
dynamicArray.addLast(e);
}
@Override
public E dequeue() {
return dynamicArray.removeFirst();
}
@Override
public E getFront() {
return dynamicArray.getFirst();
}
@Override
public int getSize() {
return dynamicArray.getSize();
}
@Override
public boolean isEmpty() {
return dynamicArray.isEmpty();
}
@Override
public String toString() {
return "DynamicArrayQueue{" +
"【隊首】dynamicArray=" + dynamicArray + "}【隊尾】";
}
}
複製代碼
測試類: DynamicArrayQueueTest
public class DynamicArrayQueueTest {
@Test
public void testArrayQueue() {
// 指定容量(capacity=6)初始化隊列
DynamicArrayQueue<String> dynamicArrayQueue = new DynamicArrayQueue(3);
System.out.println("初始隊列:" + dynamicArrayQueue);
// 準備入隊元素
List<String> enQueueElements = Arrays.asList("A", "B", "C");
// 元素入隊
enQueueElements.forEach(x -> dynamicArrayQueue.enqueue(x));
System.out.println("元素A、B、C入隊:" + dynamicArrayQueue);
// 此時若是又有一個元素D入隊,會發生擴容操做 (size == capacity)進行擴容
dynamicArrayQueue.enqueue("D");
System.out.println("元素D入隊,發生擴容:" + dynamicArrayQueue);
// 元素A出隊,會發生縮容操做(size == capacity / 2)進行縮容
dynamicArrayQueue.dequeue();
System.out.println("元素A出隊,發生縮容:" + dynamicArrayQueue);
// 元素B出隊
dynamicArrayQueue.dequeue();
System.out.println("元素B出隊:" + dynamicArrayQueue);
}
}
複製代碼
運行結果
初始隊列:DynamicArrayQueue{【隊首】dynamicArray=DynamicArray{data=[null, null, null], size=0,capacity=3}}【隊尾】
元素A、B、C入隊:DynamicArrayQueue{【隊首】dynamicArray=DynamicArray{data=[A, B, C], size=3,capacity=3}}【隊尾】
元素D入隊,發生擴容:DynamicArrayQueue{【隊首】dynamicArray=DynamicArray{data=[A, B, C, D, null, null], size=4,capacity=6}}【隊尾】
元素A出隊,發生縮容:DynamicArrayQueue{【隊首】dynamicArray=DynamicArray{data=[B, C, D], size=3,capacity=3}}【隊尾】
元素B出隊:DynamicArrayQueue{【隊首】dynamicArray=DynamicArray{data=[C, D, null], size=2,capacity=3}}【隊尾】
複製代碼
細心的盆友,會發現,由於隊列的底層是數組來實現的,隊列的出隊操做實際上就是:刪除數組中的第一個元素,後面的全部元素都要往前面挪一位;其實這樣性能是比較低下的,時間複雜度是O(n)級別的。
咱們想若是元素進行出隊操做後,可否不挪動後面的元素,還能維持隊列的特性,這樣問題不就解決了嗎?盆友能夠自行思考一下。
完整版代碼GitHub倉庫地址:Java版數據結構-隊列(數組隊列) 歡迎你們【關注】和【Star】
本篇完成的數組隊列是基於以前【Java版-數據結構-數組】動態數組來實現的,下一篇筆者會給你們介紹用循環隊列來解決數組隊列帶來的性能問題。接下來,筆者還會一一的實現其它常見的數組結構。
持續更新中,歡迎你們關注公衆號:小白程序之路(whiteontheroad),第一時間獲取最新信息!!!