隊列是一種特殊的線性表,特殊之處在於它只容許在表的前端(front)進行刪除操做,而在表的後端(rear)進行插入操做,和棧同樣,隊列是一種操做受限制的線性表。進行插入操做的端稱爲隊尾,進行刪除操做的端稱爲隊頭。隊列中沒有元素時,稱爲空隊列。故隊列又稱爲先進先出(FIFO—first in first out)線性表。前端
創建順序隊列結構必須爲其靜態分配或動態申請一片連續的存儲空間,並設置兩個指針進行管理。一個是隊頭指針front,它指向隊頭元素;另外一個是隊尾指針rear,它指向下一個入隊元素的存儲位置。後端
每次在隊尾插入一個元素是,rear增1;每次在隊頭刪除一個元素時,front增1。隨着插入和刪除操做的進行,隊列元素的個數不斷變化,隊列所佔的存儲空間也在爲隊列結構所分配的連續空間中移動。當front=rear時,隊列中沒有任何元素,稱爲空隊列。當rear增長到指向分配的連續空間以外時,隊列沒法再插入新元素,但這時每每還有大量可用空間未被佔用,這些空間是已經出隊的隊列元素曾經佔用過得存儲單元。
順序隊列中的溢出現象:
(1) "下溢"現象:當隊列爲空時,作出隊運算產生的溢出現象(數組已經爲空了繼續取出元素沒有意義)。「下溢」是正常現象,經常使用做程序控制轉移的條件。
(2)"真上溢"現象:當隊列滿時,繼續作進棧運算產生空間溢出的現象(數組越界)。「真上溢」是一種出錯狀態,應設法避免。
(3)"假上溢"現象:因爲頭尾指針都不斷前移,超出向量空間。這時整個向量空間及隊列是空的卻產生了"上溢"現象。數組
順序隊列的數組實現this
package com.jalja.org.arith; public class MySeQuence<E> { private Object [] arr; private int maxSize; private int index;//當前有效數據指針 private int front;//隊頭指針front private int rear;//隊尾指針rear public MySeQuence(int maxSize){ this.arr=new Object[maxSize]; this.front=0; this.rear=0; this.index=0; this.maxSize=maxSize; } //加入隊列 public void push(E e) { arr[rear]=e; rear++; index++; } //出隊列 public E pop() { if(isNull()) { throw new RuntimeException("MySeQuence is null"); } E e=(E)arr[front]; front++; index--; return e; } //查詢隊列內元素的個數 public int getSize() { return index; } //判斷隊列是否爲空 public boolean isNull() { return front==rear; } //隊列是否滿了 true=滿了 public boolean isFull() { return rear==maxSize; } public static void main(String[] args) { MySeQuence<Integer> myQueue=new MySeQuence<>(3); myQueue.push(1); myQueue.push(2); myQueue.push(3); System.out.println(String.format("元素個數:%s",myQueue.getSize())); System.out.println(String.format("隊列是否滿了:%s",myQueue.isFull())); while(!myQueue.isNull()) { System.out.println(myQueue.pop()); } System.out.println(String.format("元素個數:%s",myQueue.getSize())); System.out.println(String.format("隊列是否爲空:%s",myQueue.isNull())); } }
該實現會出現假上溢,固然這也是順序隊列的特色。咱們通常使用循環隊列解決這種問題。spa
把隊列空間想象成一個環形空間,環形空間中的存儲單元循環使用,用這種方法管理的隊列也就稱爲循環隊列。指針
循環隊列實現原理:code
一、不管插入或刪除,一旦rear指針增1或front指針增1 時超出了所分配的隊列空間,就讓它指向這片連續空間的起始位置,可用取餘運算rear%MaxSize和front%MaxSize來實現。orm
二、在循環隊列中,當隊列爲空時,有front=rear,而當全部隊列空間全佔滿時,也有front=rear。爲了區別這兩種狀況,規定循環隊列最多隻能有MaxSize+1個隊列元素,當循環隊列中只剩下一個空存儲單元時,隊列就已經滿了;所以,隊列判空的條件時front=rear,而隊列判滿的條件時front=rear%MaxSize。blog
循環隊列數組的實現隊列
package com.jalja.org.arith; public class MyCirQuence<E> { private Object [] arr; private int maxSize; private int index;//當前有效數據指針 private int front;//隊頭指針front private int rear;//隊尾指針rear public MyCirQuence(int maxSize){ this.arr=new Object[maxSize+1]; this.front=0; this.rear=0; this.index=0; this.maxSize=maxSize; } //加入隊列 在除法計算中 餘數必定要比除數小 public void push(E e) { if(isFull()) { throw new RuntimeException("MySeQuence is full"); } arr[rear%maxSize]=e; //數組的下表在循環 rear%maxSize rear++;//real 一直在增長 index++; } //出隊列 餘數必定要比除數小 public E pop() { if(isNull()) { throw new RuntimeException("MySeQuence is null"); } E e=(E)arr[front%maxSize]; front++; index--; return e; } //查詢隊列內元素的個數 public int getSize() { return index; } //判斷隊列是否爲空 public boolean isNull() { return front==rear; } //隊列是否滿了 true=滿了 public boolean isFull() { return !isNull() && front==rear%maxSize; } public static void main(String[] args) { MyCirQuence<Integer> myQueue=new MyCirQuence<>(3); myQueue.push(1); myQueue.push(2); myQueue.push(3); System.out.println("==>:"+myQueue.pop()); System.out.println("==>:"+myQueue.pop()); System.out.println("==>:"+myQueue.pop()); myQueue.push(4); myQueue.push(5); myQueue.push(6); while(!myQueue.isNull()) { System.out.println(myQueue.pop()); } } }