數據結構和算法 一般隊列和環形隊列

隊列

  • 隊列是一個有序列表,遵循先入先出的原則;先存入隊列的數據,要先取出(出列)。後存入的要後取出(入列)。隊列特性簡述爲First-In-First-Out(FIFO)。
  • 隊列結構可以來解決在排隊情形下的問題,但不要僅侷限於排隊系統之類的問題。在一些算法中能靈活地運用到隊列結構,其關鍵因素是其特性,FIFO。
  • 隊列可以用數組或是鏈表來實現,數組實現更加具有難度,而且比較有代表性。這篇博客我們將介紹如何使用數組實現隊列。
    在這裏插入圖片描述
  • 圖示隊列是用數組實現的:
  1. 隊列容量爲MaxSize 。
  2. 隊列的頭部由front記錄,front指向頭部元素的前一個位置;rear記錄隊列尾部,rear指向尾部元素。front和rear是數組的下標。(注意,這裏非常重要也比較容易混淆,front不是指向頭部元素,而rear是指向尾部元素)。
  3. 當元素入列時,rear數值加1;元素出列時,front數值加1。
  4. 這裏顯然,該隊列有一個缺陷:當有MaxSize數量的元素出列時或rear爲MaxSize - 1時,無法再有元素可以入列。那麼這就是一個一次性隊列,實際應用不是很大。

環形隊列

前面我們瞭解到"一次性"數組的侷限性。現在我們來改造一下數組,通過取模運算把數組想象成一個環狀的數據順序存儲結構。

  • 在改造之前我們來做一些規定,這些規定與前面隊列的規定有些區別,需要注意:
  1. front指向數組的第一個元素,front初始值爲0;rear指向最後元素的後一個位置,初始值爲0(因爲環狀的特點,最後元素的後一個位置爲0)。
  2. 數組可以儲存MaxSize個元素。
  • 根據規定我們可以得出幾個結論:
  1. 當(rear + 1)% MaxSize == front時隊列滿。
  2. 當rear == front隊列空。
  • 代碼實現:
public class CircleQueue {
    private int MaxSize;
    private int [] array;
    private int front;
    private int rear;

    public CircleQueue(int MaxSize){
        this.MaxSize = MaxSize;
        this.array = new int [MaxSize];
        front = 0;
        rear = 0;
    }

    /**
     * Judge if the array is empty.
     * @return, a boolean value
     */
    public boolean isEmpty(){
        return this.front == this.rear;
    }

    /**
     * Judge if the array is full.
     * @return, a boolean value
     */
    public boolean isFull(){
        return (this.rear + 1) % this.MaxSize == this.front;
    }

    /**
     * Make a new element queue in.
     * @param element, new element which queue in to the array.
     */
    public void queueIn(int element){
        if(!isFull()){
            //把當前入列元素放入rear位置
            this.array[this.front] = element;
            return;
        }
        //rear向後移動一個位置,這裏的取模運算是防止溢出,也是達到循環效果。
        this.rear = (this.rear + 1) % this.MaxSize;
    }

    /**
     * Make the front element queue out.
     * @return, the front element
     */
    public int queueOut() throws Exception {
        if(isEmpty()){
            throw new Exception("The array is empty!");
        }
        int temp = this.array[this.front];
        this.front = (this.front + 1) % this.MaxSize;
        return temp;
    }

    /**
     * Get a number indicating the elements in array.
     * @return, int value
     */
    public int getElementNumber(){
        //這裏的加MaxSize的處理還考慮到了實際數組中rear再front前面
        return (this.rear - this.front + this.MaxSize) % this.MaxSize;
    }

    /**
     * print out all elements in array according to the order.
     */
    public void printArray(){
        //注意,從front開始打印,數組中元素個數控制打印次數,i求餘防止溢出。
        for(int i = this.front; i < this.front + getElementNumber();i ++){
            System.out.print(this.array[(i % this.MaxSize)] + " ");
        }
    }

    /**
     * peek the front element.
     * @return, the front element.
     * @throws Exception, throw exception if the array is empty.
     */
    public int peek() throws Exception {
        if(!isEmpty()){
            throw new Exception("The array is empty!");
        }
        return this.array[this.front];
    }
}
  • 注意,實現代碼的過程中已經把注意事項和關鍵步驟寫明,環形隊列的邊界條件要仔細想明白。根據其定義和規定來實現代碼,並不難。如果想使用該隊列儲存其他類型元素(更具有實際意義),使用泛型知識改造即可,後面我們會講到該知識。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章