1.可使用數組和鏈表兩種方式來實現。java
2.遵循先入先出(FIFO)的規則,即先進入的數據先出。數組
3.屬於有序列表。數據結構
1.定義一個固定長度的數組,長度爲maxSize。測試
2.設置兩個指針first = -1(指向隊列第一個數據的前一位,這樣保證在添加第一 個數據之後頭指針爲0,和數組的下標同樣,且用於操做出隊)和last = -1(指向 隊尾,用於操做入隊)。優化
3.即first會由於出隊操做而增長,last會由於入隊操做而增長this
package 隊列; public class ArrayQueueTest { public static void main(String[] args) { ArrayQueue arrayQueue = new ArrayQueue(3); arrayQueue.addQueue("瓊"); arrayQueue.addQueue("贇"); arrayQueue.addQueue("瓏"); arrayQueue.showAllQueueData(); System.out.println(arrayQueue.getQueue()); } } class ArrayQueue{ private int maxSize;//定義隊列的最大長度 private int first ;//指向隊列頭的前一個位置!!前一個位置!!出隊方向 private int last ;//指向隊列尾部!!即最後一個數據!!!入隊方向 private String[] arr; //先建一個空的數組,具體長度未知,須要maxSize來肯定。 //構造器初始化隊列信息 public ArrayQueue(int maxSize){ this.maxSize = maxSize; this.first = -1; this.last = -1; arr = new String[maxSize]; } //判斷是否爲空 public boolean isEmpty(){ if (first == last) { System.out.println("隊列爲空~~"); return true; }else { System.out.println("隊列不爲空~~"); return false; } } //判斷隊列是否滿 public boolean isFull(){ if (last == maxSize-1) { System.out.println("隊列已滿~~"); return true; }else { System.out.println("隊列未滿~~"); return false; } } //入隊 public void addQueue(String data){ if (last == maxSize-1){ System.out.println("隊列已滿,不能再添加!!"); return; }else { last++; //添加數據只和末尾下標有關 arr[last] = data; return; } } //出隊 public String getQueue(){ if (isEmpty()) { //由於getQueue方法是int型,須要返回數據,若是無數據,也須要返回 //若是返回-1或者其餘數據,會讓人誤解獲取到的數就是-1或者其餘 //因此用拋出異常來處理 throw new RuntimeException("隊列爲空,無數據~~"); } else { first++; return arr[first]; } } //遍歷隊列全部信息 public void showAllQueueData(){ if (first == last){ return; } for (int i = 0; i < arr.length; i++) { System.out.println("arr["+i+"]"+"="+arr[i]); } } //獲取隊列頭數據 public String headQueueData(){ if (isEmpty()){ throw new RuntimeException("無數據~~~"); } return arr[++first]; } }
因爲出隊操做,使得first指針上移變大,致使數組前面空出來的位置就不能再繼續添加數據,即不能再被重複使用,這樣一個隊列只能使用一次,內存效率過低,因此須要使用環形隊列來優化解決。指針
1.first指針初始默認設置爲0,指向隊列頭部,則arr[first] 就是第一個數據。調試
2.last指針初始默認也爲0,可是會隨着增長數據然後移。code
3.隊列滿的條件:blog
(last + 1) % maxSize == first
last+1是爲了讓指針後移,並且若是不設置爲 last+1 那麼一開始的時候last爲0 , last % maxSize == 0,且first也爲0,還沒加數據就滿了。
4.隊列爲空的條件:
first == last
5.因爲判斷是否滿的時候: last+1 ,致使實際上能夠裝的數據比數組長度少 1
1.隊列初始化 :
class CircleArryQueue{ private int maxSize ; //數組長度,即隊列最大容量 private int first; //頭指針,控制出隊操做 private int last; //尾指針,控制入隊操做 private int[] arr; //數組類型,能夠換其餘的。 //構造器初始化信息 public CircleArryQueue(int maxSize){ this.maxSize = maxSize; this.arr = new int[maxSize]; this.first = 0; //這兩個能夠不加,不叫也是默認爲0 this.last = 0; } }
2.判斷隊列是否爲空:
public boolean isEmpty(){ //頭指針和尾指針同樣 則說明爲空 return last == first; }
3.判斷隊列是否滿:
/* *這裏的 last+1 主要是爲了讓指針後移,特別是在隊列尾部添加數據的時候,原本用last也能夠判斷,但 *是一開始還沒加數據的時候,若是直接用last % maxSize == first,結果是true,因此爲了解決指針後*移和判斷是否滿,用來last+1。其次,由於last+1可能會致使數組指針越界,因此用取模來控制它的範 * 圍,同時保證他會在一個固定的範圍循環變換,也利於環形隊列的實現。 */ public boolean isFull(){ return (last + 1) % maxSize == first; }
4.添加數據到隊列尾部:入隊
public void pushData(int data){ //先判斷是否滿了 if(isFull()){ System.out.println("隊列已經滿啦~~"); return; } arr[last] = data; //last+1是爲了後移,取模是爲了不指針越界,同時可讓指針循環 last = (last + 1) % maxSize; }
5.取出隊首數據:出隊
public int popData(){ if (isEmpty()) { //拋異常就能夠不用返回數據了 new RuntimeException("隊列爲空,沒有獲取到數據~~"); } //要先把first對應的數組數據保存——>first後移——>返回數據 int value = arr[first]; //first+1的操做和last+1是同樣的,取模也是 first = (first+1) % maxSize; System.out.println(value); return value; //若是不保存first指針 那麼返回的數據就不對了 //若是直接返回數據,那first指針還沒後移 也不對,因此須要使用第三方變量 }
6.展現隊列中全部數據:
public void showAllData(){ if (isEmpty()) { System.out.println("隊列爲空,沒有數據~~"); return; } //此處i不爲0,是由於有可能以前有過popData()操做,使得firs不爲0,因此最好使用 //first給i動態賦值, for (int i = first; i < first+size() ; i++) { System.out.println("arr["+i%maxSize+"]"+arr[i%maxSize]); }
7.獲取隊列中數據的總個數:
public int dataNum(){ //韓順平老師的教程上是這樣寫,可是我理解不了..........。 return (last+maxSize-first) % maxSize; }
8.查看隊首數據但不彈出:
public void seeFirstData(){ return arr[first]; }
package 練習; import java.util.Scanner; public class CircleArryQueue { public static void main(String[] args){ CircleQueue circleQueue = new CircleQueue(4); System.out.println("--------測試環形隊列--------"); char key = ' '; Scanner scanner = new Scanner(System.in); boolean flag = true; while (flag){ System.out.println("s(showAllData):查看隊列數據"); System.out.println("p(pushData):隊尾添加數據"); System.out.println("g(popData):彈出隊頭數據"); System.out.println("h(seefirstData):獲取隊頭數據"); System.out.println("e(exit):退出程序"); key = scanner.next().charAt(0); switch (key){ case 's': circleQueue.showAllData(); break; case 'p': System.out.println("輸入一個數據:"); int obj = scanner.nextInt(); circleQueue.pushData(obj); break; case 'g': circleQueue.popData(); break; case 'h': circleQueue.seeFirstData(); break; case 'e': scanner.close(); flag = false; break; default: break; } } System.out.println("程序結束~~~"); } } class CircleQueue { private int maxSize ; //數組長度,即隊列最大容量 private int first; //頭指針,控制出隊操做 private int last; //尾指針,控制入隊操做 private int[] arr; //數組類型,能夠換其餘的。 //構造器初始化信息 public CircleQueue(int maxSize){ this.maxSize = maxSize; this.arr = new int[maxSize]; this.first = 0; //這兩個能夠不加,不叫也是默認爲0 this.last = 0; } public boolean isEmpty(){ //頭指針和尾指針同樣 則說明爲空 return last == first; } /* *這裏的 last+1 主要是爲了讓指針後移,特別是在隊列尾部添加數據的時候,原本用last也能夠判斷但 *是一開始還沒加數據的時候,若是直接用last % maxSize == first,結果是true,因此爲了解決指針 *後移和判斷是否滿,用來last+1。其次,由於last+1可能會致使數組指針越界,因此用取模來控制它 *的範圍,同時保證他會在一個固定的範圍循環變換,也利於環形隊列的實現。 */ public boolean isFull(){ return (last + 1) % maxSize == first; } public void pushData(int data){ //先判斷是否滿了 if(isFull()){ System.out.println("隊列已經滿啦~~"); return; } arr[last] = data; //last+1是爲了後移,取模是爲了不指針越界,同時可讓指針循環 last = (last + 1) % maxSize; } public int popData(){ if (isEmpty()) { //拋異常就能夠不用返回數據了 throw new RuntimeException("隊列爲空,沒有獲取到數據~~"); } //要先把first對應的數組數據保存——>first後移——>返回數據 int value = arr[first]; //first+1的操做和last+1是同樣的,取模也是 first = (first+1) % maxSize; System.out.println(value); return value; //若是不保存first指針 那麼返回的數據就不對了 //若是直接返回數據,那first指針還沒後移 也不對,因此須要使用第三方變量 } //查看全部數據 public void showAllData(){ if (isEmpty()) { System.out.println("隊列爲空,沒有數據~~"); } //此處i不爲0,是由於有可能以前有過popData()操做,使得firs不爲0,因此最好使用 //first給i動態賦值, for (int i = first; i < first+dataNum() ; i++) { System.out.println("arr["+i%maxSize+"]"+arr[i%maxSize]); } } //查看有效數據個數 public int dataNum(){ //韓順平老師的教程上是這樣寫,可是我理解不了..........。 return (last+maxSize-first) % maxSize; } //查看隊列第一個數據 public int seeFirstData(){ System.out.println(arr[first]); return arr[first]; } }