1. 程式人生 > 其它 >Java 資料結構與演算法 環形佇列

Java 資料結構與演算法 環形佇列

技術標籤:java資料結構與演算法java佇列資料結構

最近由於忙其他事情,有一段時間沒有接觸一些基礎的資料結構了,前兩天遇到一個手寫環形佇列的題,都搞忘了,再次特地寫一篇部落格,記錄一下,加深印象。

環形佇列主要是有幾個公式容易忘記,其實理解了也很簡單。

幾個必要的變數說明

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());
}

執行結果如下圖