什麼是隊列?
隊列是一個有序列表,可以用數組或鏈表來實現。遵循先入先出的原則。
我們來用代碼實現一個簡單的隊列
public class ArrayQueue<T> {
private int maxSize;//表示數組的最大容量
private int front;//隊列頭
private int rear;//隊列尾
private T[] arr;//用於存放數據的數組
public ArrayQueue(int arrMaxSize){
this.maxSize = arrMaxSize;
Object[] objects = new Object[maxSize];
arr = (T[]) objects;
front = -1;//指向隊列頭的前一個位置
rear = -1;//指向隊列最後一個數據
}
//判斷隊列是否滿
public boolean isFull(){
return rear == maxSize-1;
}
//判斷隊列是否爲空
public boolean isEmpty(){
return rear == front;
}
//往隊列添加數據
public void add(T value){
//如果隊列滿了就不能添加
if(isFull()){
System.out.println("隊列已滿,不能添加數據");
return;
}
//rear後移,添加數據
arr[++rear] = value;
}
//從隊列中取出數據
public T get(){
//如果隊列是空,拋出異常
if(isEmpty()){
throw new RuntimeException("隊列爲空,不能取出數據");
}
return arr[++front];
}
//顯示隊列中的所有數據
public void show(){
if(isEmpty()){
System.out.println("隊列爲空");
return;
}
for (int i = 0; i <= rear; i++) {
System.out.println(arr[i].toString());
}
}
//顯示隊列頭的數據
public T head(){
if(isEmpty()){
throw new RuntimeException("隊列爲空");
}
return arr[front+1];
}
}
這種隊列存在一個問題,就是在存入數據再取出後,front會指向最後取出的數據的位置,如果之前存入並取出的數據已經到了隊列可以存入數據的最大值,這時候再存入數據就會提示隊列已滿。即,這個隊列是一次性的,只能使用一次。
針對這個問題進行優化,可以把這個單向隊列優化成一個環形隊列。
思路分析:
1,front變量的含義做一個調整:front指向隊列的一個元素,也就是說arr[front]就是隊列的一個元素
front初始值爲0
2,rear變量的含義做一個調整:rear指向隊列的最後一個元素的後一個位置,因爲希望留出一個空間作爲約定。
rear的初始值爲0
3,判斷隊列滿的條件:(rear+1)%maxSize == front 就是滿
4,判斷隊列爲空的條件:rear == front 就是空
5,隊列中有效數據的個數:(rear+maxSize-front)%maxSize
代碼實現:
public class CircleQueue<T> {
int maxSize;//表示數組的最大容量
/*front指向隊列的一個元素,也就是說arr[front]就是隊列的一個元素
front初始值爲0*/
int front;//隊列頭
/*rear指向隊列的最後一個元素的後一個位置,因爲希望留出一個空間作爲約定。
rear的初始值爲0*/
int rear;//隊列尾
private T[] arr;//用於存放數據的數組
public CircleQueue(int arrMaxSize){
this.maxSize = arrMaxSize;
Object[] objects = new Object[maxSize];
arr = (T[]) objects;
//int類型默認值就是0,下面兩句可以不寫
front = 0;//指向隊列頭的前一個位置
rear = 0;//指向隊列最後一個數據
}
//判斷隊列是否滿
public boolean isFull(){
return (rear+1)%maxSize == front;
}
//判斷隊列是否爲空
public boolean isEmpty(){
return rear == front;
}
//往隊列添加數據
public void add(T value){
//如果隊列滿了就不能添加
if(isFull()){
System.out.println("隊列已滿,不能添加數據");
return;
}
//直接加入數據
arr[rear] = value;
//將rear後移,這裏使用取模,因爲環形隊列要複用數組
rear = (rear+1) % maxSize;
}
//從隊列中取出數據
public T get(){
//如果隊列是空,拋出異常
if(isEmpty()){
throw new RuntimeException("隊列爲空,不能取出數據");
}
//先把front對應的值保存到一個變量,然後將front後移,這裏也得使用取模,不然會角標越界
T val = arr[front];
front = (front +1) % maxSize;
return val;
}
//顯示隊列中的所有數據
public void show(){
if(isEmpty()){
System.out.println("隊列爲空");
return;
}
//從front開始遍歷,遍歷 front+有效數據的個數 次
for (int i = front; i <= front + size(); i++) {
System.out.printf(arr[i].toString());
}
}
//計算隊列中的有效數據的個數
public int size(){
return (rear+maxSize-front)%maxSize;
}
//顯示隊列頭的數據
public T head(){
if(isEmpty()){
throw new RuntimeException("隊列爲空");
}
return arr[front];
}
}