循環隊列的定義與代碼實現

循環隊列的定義

普通的隊列有許多的不足,常常有出現“假溢出”這種現象;但是,循環隊列恰好可以解決這些問題。
循環隊列解決假溢出的辦法是後面滿了,就再從頭開始,也就是頭尾相接的循環。我們把隊列的這種頭尾相接的順序存儲結構稱爲循環隊列。

循環隊列用到的公式:

隊列滿的公式:(rear+1)%QueueSize == front
隊列長度公式:(rear-front+QueueSize)%QueueSize

front:隊列頭,指向隊列的第一個元素, 也就是說 arr[front] 就是隊列的第一個元素,初始值爲 0
rear:隊列尾,指向隊列的最後一個元素的後一個位置,因爲希望空出一個空間做爲約定,初始值爲0
QueueSize:表示數組的最大容量

循環隊列圖解:

假設我們初始化一個QueueSize = 5 的循環隊列(因爲下標從0開始),此時front和rear的值都爲0;
在這裏插入圖片描述
當我們往隊列放入4個數據後,此時的隊列已經滿了(保留一個元素空間)

此時代入隊列滿的公式進行驗算:(4+1)%5 == 0 ;顯而易見,公式左邊5%5結果爲0;公式右邊front的值也爲0;所以該公式驗算結果爲隊列滿。

此時再代入求隊列長度的公式進行驗算:(4-0+5)%5 = 4,求得結果爲4,驗算正確。
在這裏插入圖片描述
當a1、a2出隊,併入隊a5、a6後,就是下圖的樣子
在這裏插入圖片描述

循環隊列代碼實現

package com.Lindom.數據結構.隊列;
import java.util.Scanner;

public class CircleArrayQueue02 {
    public static void main(String[] args) {
        //創建一個隊列
        CircleArrayQueue queue = new CircleArrayQueue(4);
        char key; //接收用戶輸入
        Scanner scanner = new Scanner(System.in);
        boolean loop = true;
        //輸入一個菜單
        while (loop) {
            System.out.println("s(show): 顯示隊列");
            System.out.println("e(exit): 退出程序");
            System.out.println("a(add): 添加數據到隊列");
            System.out.println("g(get): 從隊列取出數據");
            System.out.println("h(head): 查看隊列頭的數據");
            key = scanner.next().charAt(0);
            switch (key){
                case 's':
                    queue.showQueue();
                    break;
                case 'a':
                    System.out.println("請輸入一個數");
                    int value = scanner.nextInt();
                    queue.addQueue(value);
                    break;
                case 'g':
                    try {
                        int res = queue.getQueue();
                        System.out.printf("取出的數據是%d\n",res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        int res = queue.headQueue();
                        System.out.printf("隊列頭的數據是%d\n",res);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    scanner.close();
                    loop =false;
                    break;
                default:
                    System.out.println("您輸入的指令無效!請重新輸入:");
                    break;
            }
        }
        System.out.println("程序退出啦!");
    }
}

//使用模擬隊列編寫ArrayQueue類
class CircleArrayQueue{
    private int maxSize;  //表示數組的最大容量
    //front 隊列頭 變量的含義做一個調整: front 就指向隊列的第一個元素, 也就是說 arr[front] 就是隊列的第一個元素
    //初始值爲 0
    private int front;
    //rear 隊列尾  變量的含義做一個調整:rear 指向隊列的最後一個元素的後一個位置. 因爲希望空出一個空間做爲約定.
    //的初始值 = 0
    private int rear;
    private int[] arr;  //該數組用於存放數據,模擬隊列

    //創建隊列的構造器
    public CircleArrayQueue(int arrMaxSize){
        maxSize = arrMaxSize;
        arr = new int[maxSize];
    }

    //判斷隊列是否滿
    public boolean isFull(){
        return (rear + 1) % maxSize == front;
    }

    //判斷隊列是否爲空
    public boolean isEmpty(){
        return rear ==front;
    }

    //添加數據到隊列
    public void addQueue(int n){
        //判斷隊列是否爲滿
        if (isFull()){
            System.out.println("隊列滿,不能加入數據!");
            return;
        }
//        arr[rear % maxSize] = n;   //一開始想出的這兩行代碼不可行,有bug,後期無法判斷隊列是否爲空
//        rear++;

        arr[rear] = n;
        rear = (rear + 1) % maxSize;
    }

    //獲取隊列數據,出隊列
    public int getQueue(){
        //判斷隊列是否爲空
        if (isEmpty()) {
            //通過拋出異常
            throw new RuntimeException("隊列空,不能獲取數據");
        }

        // 這裏需要分析出 front 是指向隊列的第一個元素
        // 1. 先把 front 對應的值保留到一個臨時變量
        // 2. 將 front 後移, 考慮取模
        // 3. 將臨時保存的變量返回
        int value = arr[front];
        front = (front + 1) % maxSize;
        return value;
    }

    //顯示隊列的所有數據
    public void showQueue(){
        //遍歷
        if (isEmpty()) {
            System.out.println("隊列爲空,沒有數據");
            return;
        }
        for (int i = front; i < front + getSize(); i++) {
            System.out.printf("arr[%d]=%d\n" , i % maxSize ,arr[i % maxSize]);
        }
    }

    public int getSize(){
        return (maxSize - front + rear) % maxSize;
    }

    //顯示隊列的頭數據,注意不是取出數據
    public int headQueue(){
        //判斷隊列是否爲空
        if (isEmpty()) {
            throw new RuntimeException("隊列爲空,沒有數據");
        }
        return arr[front];
    }
}

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
以上就是代碼的運行過程!希望本文章對你有所幫助!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章