1. 程式人生 > >資料結構(3):佇列的原理和實現

資料結構(3):佇列的原理和實現

完整程式碼拉到最底下

一、介紹

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

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

二、實現過程及思路

底層使用陣列來實現,實現的功能有插入資料到隊尾、移除隊首資料、檢視隊首資料、判斷佇列是否為空、判斷佇列是否存滿。

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

1、編寫類及屬性

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

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());
        }
    }
}