前往
大廳
主題

資料結構筆記:Queue 以Array實作

huninm | 2023-11-04 17:52:51 | 巴幣 0 | 人氣 146

隊列(Queue)是一種常見的資料結構,它遵循先進先出(FIFO)的原則,這意味著在隊列中添加的元素將按照它們被添加的順序被移除。

實作之前首先要看Queue是如何運作的,back會記錄容器內資料隊列的尾端而Front會記錄資料隊列的頭,執行Enqueue時在尾端新增資料、Dequeue時在頭端拿出資料,這就是先進先出(FIFO)




再來要進行實作,首先是創建對象,以Array實作除了記錄數據需要的矩陣以外還需要四個變數、size紀錄目前有的內容大小,capacity紀錄目前容器的容量、再來是front記住容器內資料的頭位置back記住容器內資料的尾端位置。

執行建構子時將size front back都先設為0,因為這時容器內還沒有任何資料,而記錄容量的capacity則是由宣告時提供的參數決定,如果是沒有提供參數的宣告則是使用#define SIZE 10的SIZE設為10

執行解構子時就很簡單,只要釋放動態矩陣的記憶體就好
private:
    Datatype *data;
    int size;     // 紀錄內容大小
    int capacity; // 紀錄容量
    int front;    // 以front記住容器頭位置
    int back;     // 以back記住容器尾端位置

public:
    Queue()
    {
        size = 0;
        capacity = SIZE;
        data = new Datatype[capacity];
        front = 0;
        back = 0;
    }
    Queue(int Size)
    {
        size = 0;
        capacity = Size;
        data = new Datatype[capacity];
        front = 0;
        back = 0;
    }
    ~Queue()
    {
        delete[] data;
    }

然後是方便程式編寫執行的程式Front() Bcak()分別查看隊首隊尾的資料
is_Empty() is_Full()分別判斷容器是否為空或是已滿
    Datatype Front()
    
{
        return data[front];
    }
    Datatype Bcak()
    
{
        return data[back];
    }
    bool is_Empty()
    
{
        return (size == 0);
    }
    bool is_Full()
    
{
        return (capacity == size);
    }

用Array實作Dequeue()的方式很簡單,只要把front提前也就是+1就能模擬出移出一個元素的動作
    void Dequeue() // Dequeue
    
{
        front++;
        size--;
    }

然後就是要用Array實作時需要處裡的最麻煩的部分Enqueue新增元素
在Enqueue(Datatype element)新增資料
如果容器已滿需要呼叫expand()擴張容器內空間
如果容器未滿則呼叫reset()來重製矩陣
雖然只要用循環佇列(Circular Queue)就不用reset()這麼麻煩
但是又要Circular Queue又要能擴充空間會很麻煩

    void Enqueue(Datatype element) // Enqueue
    
{
        if (is_Empty()) // 容器為空時直接新增資料於data[0]並同時設為頭尾
        {
            data[0] = element;
            back = data[0];
            front = data[0];
            size++;
            // cout << "push " << data[back] << " ";
            return;
        }
        else if (is_Full()) // 容器已滿時進行擴張
        {
            //cout << "Queue is full!" << endl;
            expand();
            size++;
            back++;
            data[back] = element;
            // cout << "push " << data[back] << " ";
            return;
        }
        else
        {
            if (back == capacity - 1)//當back已經到達矩陣中最後一個元素時需要進行重設
            {
                // cout << (capacity - 1) << endl;
                //reset();
                back++;
                data[back] = element;
                size++;
                //cout << "reset" << endl;
                return;
            }
            back++;
            data[back] = element;
            // cout << "push " << data[back] << " ";
            size++;
        }
    }
    void expand() // 擴張容器內的空間
    
{
        // 創建一個暫時的陣列temp儲存data內的資料
        Datatype temp[capacity + 1];
        int p = front;
        for (int i = 0; i < capacity; i++)
        {
            temp[i] = data[p];
            p++;
        }
        // 紀錄front and back的距離 用於修正重設後back位置
        int distance_front_back = back - front;
        delete[] data;
        // 創建一個容量+1的新data矩陣並完成資料轉移
        data = new Datatype[capacity + 1];
        for (int i = 0; i < capacity; i++)
        {
            data[i] = temp[i];
        }
        front = 0;
        back = distance_front_back;
        capacity++;
    }
    void reset() // 重設矩陣內容將整個隊列往前移 讓第一個元素能放在data[0]的位置
    
{
        // 創建一個暫時的陣列temp儲存data內的資料
        Datatype temp[capacity];
        int p = front;
        for (int i = 0; i < capacity; i++)
        {
            temp[i] = data[p];
            p++;
        }
        // 紀錄front and back的距離 用於修正重設後back位置
        int distance_front_back = back - front;
        // 完成重設
        delete[] data;
        data = new Datatype[capacity];
        for (int i = 0; i < capacity; i++)
        {
            data[i] = temp[i];
        }
        front = 0;
        back = distance_front_back;
    }



完整程式碼:
#include <iostream>

using namespace std;
#define SIZE 10
template <class Datatype>
class Queue
{

private:
    Datatype *data;
    int size;     // 紀錄內容大小
    int capacity; // 紀錄容量
    int front;    // 以front記住容器頭位置
    int back;     // 以back記住容器尾端位置

public:
    Queue()
    {
        size = 0;
        capacity = SIZE;
        data = new Datatype[capacity];
        front = 0;
        back = 0;
    }
    Queue(int Size)
    {
        size = 0;
        capacity = Size;
        data = new Datatype[capacity];
        front = 0;
        back = 0;
    }
    ~Queue()
    {
        delete[] data;
    }

    bool is_Empty()
    
{
        return (size == 0);
    }
    bool is_Full()
    
{
        return (capacity == size);
    }

    void Enqueue(Datatype element) // Enqueue
    
{
        if (is_Empty()) // 容器為空時直接新增資料於data[0]並同時設為頭尾
        {
            data[0] = element;
            back = data[0];
            front = data[0];
            size++;
            // cout << "push " << data[back] << " ";
            return;
        }
        else if (is_Full()) // 容器已滿時進行擴張
        {
            //cout << "Queue is full!" << endl;
            expand();
            size++;
            back++;
            data[back] = element;
            // cout << "push " << data[back] << " ";
            return;
        }
        else
        {
            if (back == capacity - 1)//當back已經到達矩陣中最後一個元素時需要進行重設
            {
                // cout << (capacity - 1) << endl;
                //reset();
                back++;
                data[back] = element;
                size++;
                //cout << "reset" << endl;
                return;
            }
            back++;
            data[back] = element;
            // cout << "push " << data[back] << " ";
            size++;
        }
    }
    void expand() // 擴張容器內的空間
    
{
        // 創建一個暫時的陣列temp儲存data內的資料
        Datatype temp[capacity + 1];
        int p = front;
        for (int i = 0; i < capacity; i++)
        {
            temp[i] = data[p];
            p++;
        }
        // 紀錄front and back的距離 用於修正重設後back位置
        int distance_front_back = back - front;
        delete[] data;
        // 創建一個容量+1的新data矩陣並完成資料轉移
        data = new Datatype[capacity + 1];
        for (int i = 0; i < capacity; i++)
        {
            data[i] = temp[i];
        }
        front = 0;
        back = distance_front_back;
        capacity++;
    }
    void reset() // 重設矩陣內容將整個隊列往前移 讓第一個元素能放在data[0]的位置
    
{
        // 創建一個暫時的陣列temp儲存data內的資料
        Datatype temp[capacity];
        int p = front;
        for (int i = 0; i < capacity; i++)
        {
            temp[i] = data[p];
            p++;
        }
        // 紀錄front and back的距離 用於修正重設後back位置
        int distance_front_back = back - front;
        // 完成重設
        delete[] data;
        data = new Datatype[capacity];
        for (int i = 0; i < capacity; i++)
        {
            data[i] = temp[i];
        }
        front = 0;
        back = distance_front_back;
    }
    void Dequeue() // Dequeue
    
{
        front++;
        size--;
    }

    Datatype Front()
    
{
        return data[front];
    }
    Datatype Bcak()
    
{
        return data[back];
    }
    void print()
    
{
        // cout << "front:" << front << endl;
        // cout << "back:" << back << endl;
        for (int i = 0; i < size; i++)
        {
            cout << data[(front + i)] << " ";
        }
        cout << endl;
        /*for (int i = 0; i < size; i++)
        {
            cout << data[(back - i)] << " ";
        }
        cout << endl;*/

    }
};

int main()
{
    Queue<int> test1(10);
    for (int i = 0; i < 10; i++)
    {
        test1.Enqueue(i);
    }
    test1.Dequeue();
    test1.Dequeue();
    test1.Enqueue(1);
    test1.Enqueue(1);
    test1.Enqueue(1);
    test1.Dequeue();
    test1.Dequeue();
    test1.Enqueue(1);
    test1.Enqueue(1);
    cout << "content:" << endl;
    test1.print();
    cout << "content:" << endl;
    test1.print();
    return 0;
}

創作回應

更多創作