Java資料結構

小石先生發表於2020-12-28

陣列實現迴圈佇列


前言

程式實現是Java語言。本文僅個人理解,僅供參考。若有不正之處,歡迎評論指出!


一、佇列

佇列是個什麼呢?佇列是一種資料的儲存結構,具有先入先出,後入後出的特點。
舉幾個例子(雖然可能有點····):第一個就是我們人的吃與拉!這就是一個典型的佇列,今天吃的與明天吃的相比較,今天的消化之後的**肯定比明天先排出!!!
還有就是銀行醫院等的排號辦理業務,排在前面的先辦理,辦理完畢走人,然後才輪到後面的人辦理.

圖大概就如下(取元素先取隊頭方向的,新增元素從隊尾方向加入):

在這裡插入圖片描述

二、迴圈佇列

1.概念:

當出隊一個元素頭指標向後移動一位,入隊一個元素尾指標就同樣向後移動一位。這裡的後可以理解成:順時針方向。
如圖:成環狀的佇列,就是迴圈佇列,一般約定隊尾指向的位置為空,不存資料,至於那些前輩大佬們為什麼這麼約定,下面再說說我的理解。出隊的元素總是靠近對頭方向的,入隊元素總是從靠近隊尾方向入的。
在這裡插入圖片描述

2.具有的一些特點,以及對這些特點的看法理解

初始化:front = rear = 0;

佇列空:根據初始化的狀態就是佇列空的狀態,所以就得出:front = rear的時候就是佇列空的時候。

佇列滿:(rear + 1)% maxsize = front這相當於就是判斷佇列是否為空的公式吧,為什麼呢?maxsize代表的是陣列的長度,rear與front按照陣列的下標來看,我們的約定是rear指向的地方不存值,那麼根據約定來,“存滿”就是rear加上一個1 的後等於front,這個沒毛病。

那麼問題來了,為啥留空呢?還要加1,浪費空間又麻煩?不是的,根據佇列空的狀態來看,假如沒有這個約定,那麼佇列滿的狀態(先拋開maxsize不管)也是front = rear!是不是衝突了?所以還是有作用的。

那麼對那個maxsize取餘的目的是啥?因為它是一個環狀的,定長的,所以就是為了避免加1後越出陣列的下標邊界,所以才對陣列長度進行取餘,避免了這個錯誤,也不改變結果。

判斷佇列中現存的有效的元素個數:(rear - front +maxsize) % maxSize,有些地方寫成了:(rear +maxsize - front) % maxsize,但是為了方便講解我的理解(為啥這樣寫)就看我的那個吧。

首先,我們單從maxsize來看,把rear-front看成一個正數(其實結果按理本來也就應該是一個正數,因為陣列沒有負數下標),我們對於:一個正數加上某個正數以後,再對和 – 取餘 --加上的這個數,其結果與不加是一樣的,然而當這個數是負數的時候,其結果恰好是為正數時的相反數,理解起來沒任何毛病對吧?其實隨便自己舉兩個例子就知道了。再來一句!個數不可能為負數!這樣就懂了吧?看似“多此一舉”其實不然,是為了避免出現負數個數的情況,

最後!上程式碼!(示例):

import java.util.Scanner;

/**
 * @program: 環形佇列
 * @description: 環形佇列實驗
 * @author: Mr.XiaoShi
 * @create: 2020-12-24 21:01
 **/

public class CircularQueue {
    public static void main(String[] args) {
        CircularQueue cs = new CircularQueue(8);
        Scanner sc = new Scanner(System.in);
        while (true){
            System.out.println("0、插入\t1、取出\t2、檢視隊頭\t3、遍歷佇列\t4、有效個數\t5、退出");
            /*手動捕獲自己丟擲的異常*/
            try {
                switch (sc.next()){
                    case "0":System.out.print("請輸入一個整數:");break;
                    case "1":System.out.println("對頭元素:"+cs.dequeue()+"已取出!");break;
                    case "2":System.out.println("對頭元素為:"+cs.getQueueHead());break;
                    case "3":System.out.println("當前佇列元素:\n");cs.queueShow();break;
                    case "4":System.out.println("佇列有效元素個數為:"+cs.getEffectiveNumber());break;
                    case "5":System.out.println("退出程式!");return;
                }
            }catch (Exception e){
                System.out.println(e.getMessage());    //輸出異常,提示!
            }
        }
    }
    private int maxSize;   //最大容量
    private int rear;      //尾指標
    private int front;     //頭指標
    private int [] queue;  //佇列
    /*構造器:根據傳入長度建立陣列*/
    public CircularQueue(int maxSize) {
        this.maxSize = maxSize;
        queue = new int[maxSize];
    }
    /*隊空*/
    public boolean queueEmpty(){
        return rear == front;
    }
    /*隊滿*/
    public boolean queueFull(){
        return (rear +1 ) % maxSize == front;
    }
    /*檢視有效元素個數*/
    public int getEffectiveNumber(){
        return (rear - front +maxSize) % maxSize;
    }

    /**
    *@Description: 檢視對頭元素,但不取出
    *@Param:
    *@return: front指向的(int)元素
    *@Author: your name
    *@date: 2020/12/24 0024
    **/
    public int getQueueHead(){
        if (queueEmpty()){
            throw new RuntimeException("佇列空");   //手動丟擲異常,既能結束方法,又能提示出錯誤資訊
        }
        else
            return queue[front];
    }
    /**
    *@Description: 完成入隊操作
    *@Param: element:元素的意思,插入的元素
    *@return: void
    *@Author: your name
    *@date: 2020/12/24 0024
    **/
    public void enqueue(int element){
        if (queueFull()){
            throw new RuntimeException("佇列滿,插入失敗!");  //丟擲異常
        }
        queue[rear++] = element;
        rear %= maxSize;
    }
    /**
    *@Description: 完成出隊操作
    *@Param:
    *@return: int型別的當前對頭指向元素
    *@Author: your name
    *@date: 2020/12/24 0024
    **/
    public int dequeue(){
        if (queueEmpty()){
            throw new RuntimeException("佇列空");
        }
        int tmp = queue[front++];
        front %= maxSize;
        return tmp;
    }
    /**
    *@Description: 遍歷佇列元素,但不取出
    *@Author: your name
    *@date: 2020/12/24 0024
    **/
    public void queueShow(){
        if (queueEmpty()){
            throw new RuntimeException("佇列空");
        }
        for (int i = front; i < front + getEffectiveNumber(); i++) {
            System.out.println("queue["+i % maxSize+"] = "+queue[i % maxSize]);
        }
    }
}


相關文章