隊列(queue)是隻容許在一端進行插入操做,而在另外一端進行刪除操做的線性表。是一種先進先出(First In First Out)的線性表,簡稱 FIFO。容許插入的一端稱爲隊尾,容許刪除的一端稱爲隊頭。
隊列有 2 種方式來存儲:數組 和 鏈表。
數組咱們都知道它是預先分配好長度的,所以會出現溢出現象,並且刪除元素須要向隊頭移動一個位置,時間複雜度就變成 O(n)。所以,須要一種新的方式來解決這個問題,那就是循環隊列。
隊列的這種頭尾相接的順序存儲結構稱爲循環隊列。爲了不隊列刪除元素須要移動整個隊列,使得隊頭和隊尾能夠在數組中循環變化。解決了移動元素的時間損耗,使得原本刪除是 O(n) 的時間複雜度變成了 O(1)。java
申請一片連續的存儲空間,並設置兩個指針進行管理。一個是隊頭指針front,它指向隊頭元素;另外一個是隊尾指針rear,它指向下一個入隊元素的存儲位置。通常是實現循環隊列,隊頭和隊尾會隨着入隊和出隊的變化而變化的。例如 JDK 中 ArrayBlockingQueue 就是基於循環隊列來實現的。不過它會有溢出現象,通常解決方案是若是隊列滿了,設置入隊等待時間或者返回入隊不成功。通常在肯定元素個數狀況下使用,若是不肯定元素個數,建議使用鏈表式隊列。數組
它就是基於鏈表存儲結構的隊列,能夠動態的建立和刪除元素,不用關心隊列的長度,所以不用擔憂溢出現象。新元素插入到隊尾,讀取的時候從隊頭開始,每次讀取一個元素,釋放一個元素,這就是所謂的動態建立和動態刪除。微信
好比吃飯排隊,先找服務員拿個號碼,上面會寫着前面還有 n 桌,這就至關於服務員把你加入了她們店的隊列中,當有空位置時,就直接叫你入座吃飯,當沒有空位子時,要麼排隊等候,要麼換一家吃飯。這就是隊列的用處。this
在系統設計中,好的設計是低耦合,高內聚。意思就是一個系統只作一件事情,把一件事情作好。既方便代碼維護,又方便擴展。好比又一個下單的場景,用戶下單以後須要加積分,須要給各類優惠券等等。咱們就能夠利用隊列來解偶,但真實使用通常是用開源的消息隊列,如Rocket MQ,Kafka 等等。spa
就拿上面訂單來講,原本之前是用戶下單,給用戶添加積分,給用戶發優惠券是一塊兒處理成功後返回的。如今只是處理下單,而後告訴某某系統,給某某用戶加積分,給某某用戶發優惠券了,它本身並不真正作這個動做,因此會提高系統響應,當須要保證最終一致性。通常也是用開源的消息隊列來完成的。設計
這裏是基於數組的循環隊列實現,也就是 JDK 的 ArrayBlockingQueue。有興趣的朋友也能夠看看基於鏈表的 LinkedBlockingQueue 的實現。
存儲結構指針
public class ArrayBlockingQueue<E> { //用數組來存儲元素 Object[] items; //數組裏出隊的下標 int takeIndex; //入隊的下標 int putIndex; //元素個數 int count; }
入隊code
public boolean offer(E e) { //加入數組滿了,則返回入隊失敗 if (count == items.length) { return false; } else { //得到當前數組 Object[] items = this.items; //把元素 e 加入到隊尾 items[putIndex] = e; //判斷是否是隊尾是否是倒數第二個元素 //是的話把下標爲 0 置爲隊尾,說明一圈了 if (++putIndex == items.length) { putIndex = 0; } //總數加一 count++; return true; } }
出隊隊列
public E poll() { //空隊列則返回 null if (count == 0) { return null; } else { //獲取當前數組 Object[] items = this.items; //獲取隊頭元素 E item = (E) items[takeIndex]; //置空 items[takeIndex] = null; //重置隊頭爲下標 0; if (++takeIndex == items.length) { takeIndex = 0; } //總數減一 count--; return item; } }
隊列的做用仍是很大的,好比保證輸入順序,解偶,提高系統吞吐量等等,都基於隊列的原理來實現的。隊列有數組式隊列和鏈表式隊列。數組式隊列就是基於數組存儲結構來實現的,數組的優缺點它全有。鏈表式隊列就是基於鏈表存儲結構來實現的,它也包含來鏈表的優缺點。因此在使用時能夠根絕業務需求來選擇最優的方案。rem
PS:
清山綠水始於塵,博學多識貴於勤。
我有酒,你有故事嗎?
微信公衆號:「清塵閒聊」。
歡迎一塊兒談天說地,聊代碼。