java使用數組模擬隊列、環形隊列

什麼是隊列?
隊列是一個有序列表,可以用數組或鏈表來實現。遵循先入先出的原則。

我們來用代碼實現一個簡單的隊列

public class ArrayQueue<T> {

    private int maxSize;//表示數組的最大容量
    private int front;//隊列頭
    private int rear;//隊列尾
    private T[] arr;//用於存放數據的數組

    public ArrayQueue(int arrMaxSize){
        this.maxSize = arrMaxSize;
        Object[] objects = new Object[maxSize];
        arr = (T[]) objects;
        front = -1;//指向隊列頭的前一個位置
        rear = -1;//指向隊列最後一個數據
    }

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

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

    //往隊列添加數據
    public void add(T value){
        //如果隊列滿了就不能添加
        if(isFull()){
            System.out.println("隊列已滿,不能添加數據");
            return;
        }
        //rear後移,添加數據
        arr[++rear] = value;
    }

    //從隊列中取出數據
    public T get(){
        //如果隊列是空,拋出異常
        if(isEmpty()){
            throw new RuntimeException("隊列爲空,不能取出數據");
        }

        return arr[++front];
    }

    //顯示隊列中的所有數據
    public void show(){
        if(isEmpty()){
            System.out.println("隊列爲空");
            return;
        }
        for (int i = 0; i <= rear; i++) {
            System.out.println(arr[i].toString());
        }
    }

    //顯示隊列頭的數據
    public T head(){
        if(isEmpty()){
            throw new RuntimeException("隊列爲空");
        }
        return arr[front+1];
    }
}

這種隊列存在一個問題,就是在存入數據再取出後,front會指向最後取出的數據的位置,如果之前存入並取出的數據已經到了隊列可以存入數據的最大值,這時候再存入數據就會提示隊列已滿。即,這個隊列是一次性的,只能使用一次。

針對這個問題進行優化,可以把這個單向隊列優化成一個環形隊列。

思路分析:

1,front變量的含義做一個調整:front指向隊列的一個元素,也就是說arr[front]就是隊列的一個元素

front初始值爲0

2,rear變量的含義做一個調整:rear指向隊列的最後一個元素的後一個位置,因爲希望留出一個空間作爲約定。

rear的初始值爲0

3,判斷隊列滿的條件:(rear+1)%maxSize == front  就是滿

4,判斷隊列爲空的條件:rear == front 就是空

5,隊列中有效數據的個數:(rear+maxSize-front)%maxSize

代碼實現:

public class CircleQueue<T> {

     int maxSize;//表示數組的最大容量

    /*front指向隊列的一個元素,也就是說arr[front]就是隊列的一個元素
    front初始值爲0*/
     int front;//隊列頭

    /*rear指向隊列的最後一個元素的後一個位置,因爲希望留出一個空間作爲約定。
    rear的初始值爲0*/
     int rear;//隊列尾

    private T[] arr;//用於存放數據的數組

    public CircleQueue(int arrMaxSize){
        this.maxSize = arrMaxSize;
        Object[] objects = new Object[maxSize];
        arr = (T[]) objects;

        //int類型默認值就是0,下面兩句可以不寫
        front = 0;//指向隊列頭的前一個位置
        rear = 0;//指向隊列最後一個數據
    }


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

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

    //往隊列添加數據
    public void add(T value){
        //如果隊列滿了就不能添加
        if(isFull()){
            System.out.println("隊列已滿,不能添加數據");
            return;
        }
        //直接加入數據
        arr[rear] = value;
        //將rear後移,這裏使用取模,因爲環形隊列要複用數組
        rear = (rear+1) % maxSize;
    }

    //從隊列中取出數據
    public T get(){
        //如果隊列是空,拋出異常
        if(isEmpty()){
            throw new RuntimeException("隊列爲空,不能取出數據");
        }

        //先把front對應的值保存到一個變量,然後將front後移,這裏也得使用取模,不然會角標越界
        T val = arr[front];
        front = (front +1) % maxSize;
        return val;
    }

    //顯示隊列中的所有數據
    public void show(){
        if(isEmpty()){
            System.out.println("隊列爲空");
            return;
        }
        //從front開始遍歷,遍歷 front+有效數據的個數 次
        for (int i = front; i <= front + size(); i++) {
            System.out.printf(arr[i].toString());
        }
    }

    //計算隊列中的有效數據的個數
    public int size(){
        return (rear+maxSize-front)%maxSize;
    }

    //顯示隊列頭的數據
    public T head(){
        if(isEmpty()){
            throw new RuntimeException("隊列爲空");
        }
        return arr[front];
    }
}

 

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