數據結構(3):隊列的原理和實現

完整代碼拉到最底下

一、介紹

隊列顧名思義就像我們生活中排隊一樣,先進先出。

image

如上圖所示,25、16、5、9依次在隊列中,按照順序拿出的數據也分別是25、26、5、9。

二、實現過程及思路

底層使用數組來實現,實現的功能有插入數據到隊尾、移除隊首數據、查看隊首數據、判斷隊列是否爲空、判斷隊列是否存滿。

將隊列的元素存儲在數組的某個區間內,隊列在數組中是連續的,所以使用變量標記隊列在數組中的位置。

1、編寫類及屬性

我們可以使用elements變量標記隊列中元素的數量,使用front變量標記隊首元素在數組的索引,end變量標記隊尾元素在數組中的索引。

image

public class MyQueue {
    
    private Object[] arr;//存放隊列元素的數組
    private int elements;//隊列元素數量
    private int front;//隊頭元素在數組中的索引
    private int end;//隊尾元素在數組中的索引
    
    
    public MyQueue() {
        arr = new Object[10];
        elements = 0;
        front = 0;
        end = -1;
    }

    public MyQueue(int maxSize) {
        arr = new Object[maxSize];
        elements = 0;
        front = 0;
        end = -1;
    }    
}

2、隊列是否爲空

標記隊列元數量的變量 elements 爲 0 即爲空

public boolean isEmpty() {
    return elements == 0;
}

3、隊列是否已經滿了

隊列元素個數與數組的長度相等即爲滿

public boolean isFull() {
    return elements == arr.length;
}

4、獲取隊頭元素

獲取數組中索引爲 front的元素

public Object peek() {
    return arr[front];
}

5、移除隊首元素

每次都是移除數組中索引爲 front 的元素,下一個元素就變成了隊首,即front+1,隊列元素個數elements-1。共有三種情況要考慮,如果隊列已經空了就無須做任何操作,如果已經是最後一個元素,直接將標記位置的變量重置即可,其他情況正常操作。

public Object remove() {
    if (isEmpty()) {
        throw new RuntimeException("隊列已經是空的,放心使用吧");
    }
    Object value = arr[front++];
    //如果已經是最後一個元素了,將指針重置即可
    if (elements == 1) {
        end = -1;
        front = 0;
        elements = 0;
    } else {
        elements--;
    }
    return value;
}

6、插入

我們編寫一個持續可用的隊列,所以要考慮到以下情況。

(1)存儲隊列的數組滿了(隊列滿了),這個好理解,滿了就無法向隊尾加入元素了。

(2)因爲隊列在數組中是連續的,如果隊列的元素在數組中最後,需要將元素從隊首到隊尾移到數組中第一位,也就是將後面的位置空出來(參考下圖)。

public void insert(Object value) {
    //檢測隊列是否已經滿了
    if (isFull()) {
        throw new RuntimeException("隊列內元素已達到設定長度");
    }

    //如果後面沒有空位置,將餘下元素放到數組的頭
    if (elements > 1 && end == arr.length - 1) {
        int i = 0;
        for (; i < elements; i++, front++) {
            arr[i] = arr[front];
        }
        front = 0;
        end = i-1;
    }
    //其他情況正常向後添加元素
    arr[++end] = value;
    elements++;
}

7、測試

public static void main(String[] args) {
    MyQueue queue = new MyQueue(4);
    queue.insert(11);
    queue.insert(12);
    queue.insert(13);
    queue.insert(14);

    queue.remove();
    queue.remove();
    queue.insert(16);
    //queue.remove();
    //queue.remove();
    
    //queue.insert(19);
    //queue.insert(20);
    queue.remove();

    queue.remove();

    queue.insert(21);
    queue.insert(22);

    while (!queue.isEmpty()) {
        System.out.println(queue.remove());
    }
}

三、完整代碼

package com.jikedaquan.datastruct;

public class MyQueue {
    private Object[] arr;
    private int elements;//隊列元素數量
    private int front;//隊頭元素在數組中的索引
    private int end;//隊尾元素在數組中的索引

    public MyQueue() {
        arr = new Object[10];
        elements = 0;
        front = 0;
        end = -1;
    }

    public MyQueue(int maxSize) {
        arr = new Object[maxSize];
        elements = 0;
        front = 0;
        end = -1;
    }

    //從隊尾插入
    public void insert(Object value) {
        //檢測隊列是否已經滿了
        if (isFull()) {
            throw new RuntimeException("隊列內元素已達到設定長度");
        }

        //如果後面沒有空位置,將餘下元素放到數組的頭
        if (elements > 1 && end == arr.length - 1) {
            int i = 0;
            for (; i < elements; i++, front++) {
                arr[i] = arr[front];
            }
            front = 0;
            end = i-1;
        }
        arr[++end] = value;
        elements++;

    }

    //刪除數據,從隊頭刪除
    public Object remove() {
        if (isEmpty()) {
            throw new RuntimeException("隊列已經是空的,放心使用吧");
        }
        Object value = arr[front++];
        //如果已經是最後一個元素了,將指針重置即可
        if (elements == 1) {
            end = -1;
            front = 0;
            elements = 0;
        } else {
            elements--;
        }
        return value;
    }

    //查看數據,從隊頭查看
    public Object peek() {
        return arr[front];
    }

    //判斷是否爲空
    public boolean isEmpty() {
        return elements == 0;
    }

    public boolean isFull() {
        return elements == arr.length;
    }

    public static void main(String[] args) {
        MyQueue queue = new MyQueue(4);
        queue.insert(11);
        queue.insert(12);
        queue.insert(13);
        queue.insert(14);

        queue.remove();
        queue.remove();
        queue.insert(16);
//        queue.remove();
//        queue.remove();

//        queue.insert(19);
//        queue.insert(20);
        queue.remove();

        queue.remove();

        queue.insert(21);
        queue.insert(22);

        while (!queue.isEmpty()) {
            System.out.println(queue.remove());
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章