1-3 队列:数组实现

队列是一种遵循FIFO(先进先出)原则的线性数据结构。第一个插入的元素是第一个被移除的元素。

使用数组声明队列

队列可以使用数组实现,主要有两种方式:

  • 无限(或动态增长)数组队列
  • 固定大小数组队列

无限(或动态增长)数组队列

我们可以使用概念上无限的数组实现队列,只需维护一个front指针。front指针跟踪第一个有效元素。

入队(Enqueue):在末尾的下一个可用位置插入元素,不需要rear指针。
出队(Dequeue):移除front位置的元素并将front指针递增。

front之前的空间永远不会被重用,与基本数组实现不同,我们在每次出队后不需要移动元素。这确保了入队和出队操作都以O(1)时间运行,设计简单。

局限性

  • 空间浪费:front指针之前的元素永远不会被重用,如果许多元素被出队,内存可能会被浪费。
  • 无限数组假设:我们假设数组在概念上是无限的。实际上,内存是有限的,因此非常大的队列可能导致内存问题。

固定大小数组队列

在本文中,我们主要讨论使用固定大小数组实现队列。在这种基于数组的队列中,我们维护:

  • 一个固定大小的数组arr[]来存储元素。
  • 一个变量size来跟踪队列中当前的元素数量。
  • 一个变量capacity来表示队列可以容纳的最大元素数量。
#include <iostream>

class MyQueue 
{
    // 存储队列元素的数组
    int* arr;
    
    // 队列可以容纳的最大元素数量
    int capacity;
    
    // 队列中当前的元素数量
    int size;

 public:
    explicit MyQueue(int c) 
    {
        capacity = c;
        arr = new int[capacity];
        size = 0;
    }
    
    ~MyQueue() 
    {
        delete[] arr;
    }
};

队列操作

入队(插入)

如果空间可用,在队列末尾添加元素;否则会导致溢出条件。

时间复杂度:O(1),空间复杂度:O(1)

void enqueue(int x) 
  {
    if (size == capacity) 
    {
        cout << "Queue Overflow" << endl;
        return;
    }
    arr[size++] = x;
}

出队

从队列前端移除元素;如果队列为空,会导致下溢条件。

时间复杂度:O(n)(因为需要移位),空间复杂度:O(1)

void dequeue() 
{
    if (size == 0) 
    {
        cout << "Queue Underflow" << endl;
        return;
    }
    for (int i = 1; i < size; i++) 
    {
        arr[i - 1] = arr[i];
    }
    size--;
}

获取队首元素(查看)

如果不为空返回第一个元素,否则返回-1。

时间复杂度:O(1),空间复杂度:O(1)

int getFront() 
{
    if (size == 0) 
    {
        cout << "Queue is empty" << endl;
        return -1;
    }
    return arr[0];
}

获取队尾元素

如果不为空返回最后一个元素,否则返回-1。

时间复杂度:O(1),空间复杂度:O(1)

int GetRear() 
{
    if (isEmpty()) 
    {
        cout << "Queue is empty!" << endl;
        return -1;
    }
    return arr[size - 1];
}

判断是否为空

检查队列是否有任何元素。

如果队列为空返回true,否则返回false。

时间复杂度:O(1),空间复杂度:O(1)

bool isEmpty() 
{
    return size == 0;
}

判断是否已满

检查队列是否已达到最大容量。

如果队列已满返回true,否则返回false。

时间复杂度:O(1),空间复杂度:O(1)

bool isFull() 
{
    return size == capacity;
}

使用数组实现队列的完整代码

#include <iostream>

class MyQueue {
    // 存储队列元素的数组
    int* arr;

    // 队列可以容纳的最大元素数量
    int capacity;

    // 队列中当前的元素数量
    int size;

 public:
    explicit MyQueue(int c) 
    {
        capacity = c;
        arr = new int[capacity];
        size = 0;
    }

    ~MyQueue() 
    {
        delete[] arr;
    }

    bool isEmpty() 
    {
        return size == 0;
    }

    bool isFull() 
    {
        return size == capacity;
    }

    // 在队列末尾添加元素x
    void inqueue(int x) 
    {
        if (IsFull()) 
        {
            std::cout << "Queue is full!\\n";
            return;
        }
        arr[size] = x;
        size++;
    }

    // 移除队列的前端元素
    void iequeue() 
    {
        if (isEmpty()) 
        {
            std::cout << "Queue is empty!\\n";
            return;
        }
        for (int i = 1; i < size; i++) 
        {
            arr[i - 1] = arr[i];
        }
        size--;
    }

    // 返回队列的前端元素
    int getFront() 
    {
        if (isEmpty()) 
        {
            std::cout << "Queue is empty!\\n";
            return -1;
        }
        return arr[0];
    }

    // 返回队列的最后一个元素
    int getRear() {
        if (isEmpty()) 
        {
            std::cout << "Queue is empty!" << endl;
            return -1;
        }
        return arr[size - 1];
    }
};

int main() 
{
    MyQueue q(3);

    q.Enqueue(10);
    q.Enqueue(20);
    q.Enqueue(30);
    std::cout << "Front: " << q.getFront() << endl;

    q.Dequeue();
    std::cout << "Front: " << q.getFront() << endl;
    std::cout << "Rear: " << q.getRear() << endl;

    q.Enqueue(40);

    return 0;
}

输出

Front: 10
Front: 20
Rear: 30

我们可以注意到出队操作是O(n),这是不可接受的。入队和出队操作都应该有O(1)的时间复杂度。这就是为什么如果我们希望使用数组实现队列(因为数组具有缓存友好和随机访问等优势),我们会使用循环数组实现队列

posted @ 2026-03-20 17:25  游翔  阅读(1)  评论(0)    收藏  举报