(上一篇隊列:https://www.cnblogs.com/yxm2020/p/12676323.html )
1、假溢出
系統作為隊列用的存儲區還沒有滿,但隊列卻發生了溢出,我們把這種現象稱為"假溢出"。
因為隊列遵從從隊尾存入數據,從隊頭取數據,所以紅框部分的空間就不能繼續存入新的數據,此時隊列有多余的空間,卻不能存入值,這種現象就叫做假溢出現象
2、循環隊列介紹
充分利用了空間,解決“假溢出”的問題
【循環隊列思想】
將普通隊列想象成邏輯上的首位相連的圓環,把這個叫循環隊列,在循環隊列中,當隊列為空時,有front=rear,而當所有隊列空間全占滿時,也有front=rear。為了區別這兩種情況,規定循環隊列最多只能有MaxSize-1個隊列元素,當循環隊列中只剩下一個空存儲單元時,隊列就已經滿了。因此,隊列判空的條件是front=rear,而隊列判滿的條件是front=(rear+1)%MaxSize
。
【為什么要空一個存儲單元】
我有想過這個問題,rear一直是空的,我為什么不能在里面存值,而我隊列判滿的條件也是front=(rear+1)%MaxSize,似乎很合情合理,那么我們把目光轉到開頭,當我存入第一個數字的時候,隊尾肯定是要加一的,如果我front,rear的初始值像普通隊列那樣都為-1,才不會自相矛盾,但是這是個循環隊列,當第二輪的時候,這個就不管用了,所以一定要空一個存儲單元。
3、Java代碼實現
1、確定有哪些元素
- 頭尾標志:rear,front,並且初值都為0
- 最大長度
- 定義一個數組,這次我決定用泛型(泛型數組,這部分知識很有意思,建議嘗試)
【代碼實現】
public class CircleArrayQueue<T> {
//最大長度
private int maxSize;
//頭尾標志
private int rear;
private int front;
T[] array;
public CircleArrayQueue(int maxSize,Class<T> type){
init(maxSize,type);
}
//初始化
private void init(int maxSize,Class<T> type){
//個人覺得這個是個黑盒實現,使用的人傳入maxSize大小,你不應該只給他創造maxSize-1的大小
this.maxSize = maxSize+1;
rear = 0;
front = 0;
array = (T[]) Array.newInstance(type,this.maxSize);
}
//判斷隊滿
public boolean isFull(){
//rear和front的變化一定要記得是個循環,不然很容易搞錯,我就搞錯好多次
return (rear+1)%maxSize == front;
}
//判斷隊空
public boolean isEnpty(){
return rear == front;
}
//插入
public void add(T t){
if(isFull()){
throw new RuntimeException("隊列已滿");
}
array[rear] = t;
rear = (rear+1)%maxSize;
}
//取元素
public T get(){
if(isEnpty()){
throw new RuntimeException("隊列為空");
}
T t = array[front];
front = (front+1)%maxSize;
return t;
}
//獲得長度
public int size(){
return (rear+maxSize-front)%maxSize;
}
//打印所有數據
public void showData(){
int length = this.size();
int head = front;
for (int i = 0; i < length; i++) {
//先執行array[head],再自加
System.out.println(array[head]);
head = (head+1)%maxSize;
}
}
}
個人寫的代碼水平比較低,僅供參考。