Java 資料結構與演算法 環形佇列
阿新 • • 發佈:2021-01-11
最近由於忙其他事情,有一段時間沒有接觸一些基礎的資料結構了,前兩天遇到一個手寫環形佇列的題,都搞忘了,再次特地寫一篇部落格,記錄一下,加深印象。
環形佇列主要是有幾個公式容易忘記,其實理解了也很簡單。
幾個必要的變數說明
int[] arr:儲存佇列的陣列,也可以用連結串列做,這裡不多贅述
int maxSize:陣列的長度,也是佇列的最大長度,通常是初始化佇列時傳入
int front:隊頭指標,記錄陣列中佇列的隊頭下標
int size:當前的佇列的長度
注:以前學習資料結構時,一般老師或者教材在實現佇列都是用的front和rear雙指標來表示隊頭隊尾,但其實一個環形佇列,我們只需要一個頭指標即可。
下面的poll、peek這些命名我是參考的Java中Queue佇列操作
公式1:offer入隊操作,向隊尾新增元素時,需要計算出佇列長度,將新的元素新增到隊尾
index = (front + size) % maxSize;
公式2:poll出隊操作,取出隊頭元素時,front需要向陣列後面移動一位
front = (front + 1) % maxSize;
公式3:getLast獲取隊尾元素操作,該操作一般佇列不提供,但這裡順便提一下
last= (front + size - 1) % maxSize;
其實公式1看懂了,公式3很容易理解,就是在隊尾的後一個元素插入元素嘛
下面直接上程式碼
/** * 陣列實現環形佇列 */ public class LoopArrayQueue { private int[] arr; // 該資料用於存放資料, 模擬佇列 private int maxSize; // 表示陣列的最大容量 private int front; // 佇列頭,指向佇列的第一個元素 private int size;//記錄當前陣列中佇列的長度 // 建立佇列的構造器 public LoopArrayQueue(int arrMaxSize) { maxSize = arrMaxSize; arr = new int[maxSize]; front = 0; size = 0; } // 判斷佇列是否滿 public boolean isFull() { return size == maxSize;//陣列長度和佇列長度相同說明佇列已滿 } // 判斷佇列是否為空 public boolean isEmpty() { return size == 0; } // 新增資料到佇列,入佇列 public void offer(int n) { // 判斷佇列是否滿 if (isFull()) throw new RuntimeException("佇列滿,不能加入資料~"); int index = (front + size) % maxSize;//計算出要存放的位置,相當於rear arr[index] = n; size++;//佇列長度+1 } // 獲取佇列的頭資料,同時刪除資料 public int poll() { if (isEmpty()) throw new RuntimeException("佇列空,不能取資料"); int res = arr[front]; front = (front + 1) % maxSize; //隊頭的位置向後移動 size--;//佇列長度-1 return res; } // 讀取佇列的頭資料, 不刪除資料 public int peek() { if (isEmpty()) throw new RuntimeException("佇列空的,沒有資料~~"); return arr[front];//front起始就指向陣列開始 } /** * 讀取隊尾元素 - 一般佇列不提供這個個操作 * 只要知道隊頭位置、陣列長度、佇列個數就可以用下面的公式求出隊尾位置 * tailIndex = (headIndex + count −1) % capacity * 得到隊尾位置後,即可對整個環形佇列進行操作。 */ public int getLast(){ if(isEmpty()) throw new RuntimeException("佇列空的,沒有資料~~"); int tail = (front + size - 1) % maxSize; return arr[tail]; } // 顯示佇列的所有資料 public void display() { if (isEmpty()) throw new RuntimeException("佇列空的,沒有資料~~"); //遍歷應該從front開始遍歷,遍歷次數為佇列有效個數 System.out.print("當前隊伍:"); for (int i = front; i < front+size; i++) { System.out.print(arr[i]+"\t"); } System.out.println(""); } }
下面進行測試一下:
public static void main(String[] args) {
LoopArrayQueue queue = new LoopArrayQueue(3);//傳入佇列的長度,這裡長度是傳入的數值-1
queue.offer(11);
queue.offer(22);
queue.offer(33);
System.out.println("顯示隊頭:"+queue.peek());
System.out.println("顯示隊尾:"+queue.getLast());
System.out.println("隊頭出隊:"+queue.poll());
System.out.println("隊頭出隊:"+queue.poll());
queue.display();
System.out.println("顯示隊頭:"+queue.peek());
}
執行結果如下圖