【數據結構+算法】隊列——用數組實現環形隊列

在我上一個博客中,我們提到數組實現隊列時,不能實現代碼的複用,優化方法是可以改成一個環形的數組(進行取餘)。所以本次我將總結如何用數組實現環形隊列。

思路:

1、對front變量進行一個調整:front指向隊列的第一個元素,即arr[front]爲隊列的第一個元素;front=0

2、對rear變量也進行相應的調整:reart指向隊列最後一個元素的後一個位置,預留一個空間;rear=0

3、隊滿:(rear+1) % maxSize = front

4、對空:rear == front

5、隊列中的有效數據:(rear + maxSize - front) % maxSize
(rear可能小於maxSize,取餘是爲了獲取在環形隊列上真實位置)

具體實現代碼如下:
(1)、判斷隊列是否滿
(2)、判斷隊列是否爲空
(3)、添加數據到隊列中
(4)、獲取隊列的數據,出隊列;
(5)、顯示當前隊列數據;
(6)、顯示隊列的頭數據,注意不是取出數據;

package com.ycx.queue;

import java.util.Scanner;

public class CircleArrayQueueDemo {
    public static void main(String[] args) {

        //測試
        System.out.println("測試數組模擬環形隊列");

        //創建一個環形隊列
        CircleArray queue = new CircleArray(4);//有一個空位置 有效數據最大是3
        char key = ' ';//接受用戶輸入
        Scanner input = new Scanner(System.in);
        boolean flag = true; //控制循環 默認死循環

        //輸出菜單
        while (flag){
            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=input.next().charAt(0);//接受收一個字符
            switch (key){
                case 's':
                    queue.showQueue();
                    break;
                case 'a':
                    System.out.println("輸一個數");
                    int val=input.nextInt();
                    queue.addQueue(val);
                    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':    //退出程序
                    input.close();//關閉
                    flag=false;
                    break;

                default:
                    break;
            }
        }
        System.out.println("程序退出");
    }
}


class CircleArray{
    private  int maxSize;
    //表示數組的最大容量
    private  int front;
    //front變量含義做一個調整:指向隊列的第一個元素,arr[front]即爲隊列的第一個元素
    //front=0
    private  int rear;
    //rear變量含義做一個調整:rear指向隊列的最後一個元素的後一個位置,預留一個位置
    //rear=0
    private  int[] arr;
    // 該數組用於存放數據,模擬隊列


    public CircleArray(int arrMaxSize){
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        front=0;
        rear=0;
    }


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

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


    //3.添加數據到隊列中
    public void addQueue(int n) {
        //判斷隊列是否爲滿
        if (isFull()) {
            System.out.println("隊列已滿,不能加入數據");
        }
        arr[rear] = n;
        //直接將數據加入 因爲rear本身指的就是 後一個元素
        rear = (rear + 1) % n;
        //將rear 後移 並取模 (環形 當rear走到最後一個位置時,取模就可以到前面的位置)
    }

        //4.獲取隊列的數據,出隊列
        public  int getQueue(){
            if(isEmpty()){
                throw new RuntimeException("隊列空,不能取數據");
            }

            //這裏需要分析出front是指向隊列的第一個元素
            //①. 先把front對應的值保留到一個臨時變量;
            //②. 將front後移,考取取模(因爲front也可能走到最後一個元素,就會越界)
            //③. 將臨時保存的變量返回
            int value = arr[front];
            front = (front+1) % maxSize;
            return value;
        }


        //5.顯示當前隊列數據
    public void showQueue() {
        //遍歷
        if(isEmpty()){
            System.out.println("當前隊列爲空");
            return;
        }

        //思路: 從front開始遍歷 一共有front+有效數據個數
        for (int i = front ;i <front+size(); i++) {
            System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]); //格式化輸出
                                             // i可能也會超出下標(環形)
        }
    }

    //求出當前有效數據個數
    public int size(){
        return (rear+maxSize-front)%maxSize;
        // rear=1 front=0 maxSize=3
    }


    //6.顯示隊列的頭數據,注意不是取出數據
    public int headQueue(){
        if(isEmpty()){
            throw new RuntimeException("隊列爲空");
        }
        return arr[front]; //注意:front本身就指向第一個元素
    }



}

運行結果如下:
在這裏插入圖片描述

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