实现一个简单的环形队列

实现一个简单的环形队列



一、什么是环形队列?

环形队列的定义

环形队列(Circular Queue)是一种特殊的数据结构,旨在高效地管理和利用存储空间。与传统的线性队列相比,环形队列的主要特点在于,它的队尾和队头可以在同一存储空间中循环使用,从而避免了空间浪费。

环形队列的原理

  1. 数据结构

    • 环形队列通常使用一个固定大小的数组来存储元素。
    • 定义两个指针:
      • front:指向队头元素的位置。
      • rear:指向队尾元素的下一个位置。
  2. 容量

    • 最大容量通常比数组的大小少一个,以便能够区分空队列和满队列的状态。这是因为当 frontrear 相等时,队列被认为是空的,而当 (rear + 1) % maxSize == front 时,队列被认为是满的。
  3. 入队(enqueue)

    • 将新元素添加到 rear 指向的位置,然后更新 rear 指针为 (rear + 1) % maxSize。如果 rear 指针达到数组的末尾,它将重新回到数组的起始位置。
  4. 出队(dequeue)

    • front 指向的位置移除元素,然后更新 front 指针为 (front + 1) % maxSize。同样,front 指针在到达数组末尾时会循环回到开头。
  5. 判断队列状态

    • 空队列:当 frontrear 相等时,队列为空。
    • 满队列:当 (rear + 1) % maxSize == front 时,队列满。

二、环形队列功能实现

1.构造初始化

    // 构造函数,初始化队列大小
    CircularQueue(int size) : maxSize(size + 1), front(0), rear(0)
    {
        data.resize(maxSize); // 根据最大大小调整数据存储空间
    }

2.入队操作

    // 入队操作
    bool enqueue(const T &item)
    {
        if (isFull()) // 检查队列是否已满
        {
            throw std::runtime_error("Queue is full!"); // 抛出异常
            return false;                               // 这个返回语句不会被执行
        }
        data[rear] = item;           // 将新元素放入队尾
        rear = (rear + 1) % maxSize; // 更新队尾指针
        return true;                 // 入队成功
    }

3.出队操作

    // 出队操作
    bool dequeue()
    {
        if (isEmpty()) // 检查队列是否为空
        {
            throw std::runtime_error("Queue is empty!"); // 抛出异常
            return false;                                // 这个返回语句不会被执行
        }
        front = (front + 1) % maxSize; // 更新队头指针
        return true;                   // 出队成功
    }

4.查看队头元素

    // 查看队头元素
    T peek() const
    {
        if (isEmpty()) // 检查队列是否为空
        {
            throw std::runtime_error("Queue is empty!"); // 抛出异常
        }
        return data[front]; // 返回队头元素
    }

5.判断队列是否为空

    // 检查队列是否为空
    bool isEmpty() const
    {
        return front == rear; // front 和 rear 相等时队列为空
    }

6.判断队列是否满

    // 检查队列是否已满
    bool isFull() const
    {
        return (rear + 1) % maxSize == front; // 满的条件
    }

7.返回队列当前大小

    // 返回当前队列的有效元素个数
    int size() const
    {
        return (rear - front + maxSize) % maxSize; // 计算有效元素个数
    }

三、完整代码及测试

#include <iostream>
#include <vector>
#include <stdexcept>

// 环形队列模板类
template <typename T>
class CircularQueue
{
public:
    // 构造函数,初始化队列大小
    CircularQueue(int size) : maxSize(size + 1), front(0), rear(0)
    {
        data.resize(maxSize); // 根据最大大小调整数据存储空间
    }

    // 入队操作
    bool enqueue(const T &item)
    {
        if (isFull()) // 检查队列是否已满
        {
            throw std::runtime_error("Queue is full!"); // 抛出异常
            return false;                               // 这个返回语句不会被执行
        }
        data[rear] = item;           // 将新元素放入队尾
        rear = (rear + 1) % maxSize; // 更新队尾指针
        return true;                 // 入队成功
    }

    // 出队操作
    bool dequeue()
    {
        if (isEmpty()) // 检查队列是否为空
        {
            throw std::runtime_error("Queue is empty!"); // 抛出异常
            return false;                                // 这个返回语句不会被执行
        }
        front = (front + 1) % maxSize; // 更新队头指针
        return true;                   // 出队成功
    }

    // 查看队头元素
    T peek() const
    {
        if (isEmpty()) // 检查队列是否为空
        {
            throw std::runtime_error("Queue is empty!"); // 抛出异常
        }
        return data[front]; // 返回队头元素
    }

    // 检查队列是否为空
    bool isEmpty() const
    {
        return front == rear; // front 和 rear 相等时队列为空
    }

    // 检查队列是否已满
    bool isFull() const
    {
        return (rear + 1) % maxSize == front; // 满的条件
    }

    // 返回当前队列的有效元素个数
    int size() const
    {
        return (rear - front + maxSize) % maxSize; // 计算有效元素个数
    }

private:
    std::vector<T> data;      // 存储队列元素的向量
    int front, rear, maxSize; // front: 队头, rear: 队尾, maxSize: 最大容量
};

int main()
{
    CircularQueue<int> cq(5); // 创建一个最大容量为5的环形队列

    cq.enqueue(1); // 入队 1
    cq.enqueue(2); // 入队 2
    cq.enqueue(3); // 入队 3

    std::cout << "Front item: " << cq.peek() << std::endl; // 输出队头元素: 1

    cq.dequeue();                                                        // 出队操作
    std::cout << "Front item after dequeue: " << cq.peek() << std::endl; // 输出队头元素: 2

    std::cout << "Current size: " << cq.size() << std::endl; // 输出当前队列大小: 2

    return 0; // 程序结束
}

环形队列的优势

  • 空间利用:环形队列能够有效利用固定大小的数组,避免了线性队列中因元素出队导致的空间浪费。
  • 操作效率:入队和出队操作的时间复杂度均为 O(1),即常数时间,适合需要频繁插入和删除的场景。

适用场景

环形队列在操作系统的任务调度、数据缓冲、流媒体数据处理等场景中广泛应用。通过循环利用空间,环形队列能够高效地处理数据流和任务调度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值