C/C++数据结构之用数组实现队列

概述

要在C/C++中用数组自行实现队列,我们首先需要理解队列提供的基本操作。这些操作主要包括以下6个接口。

Enqueue:向队尾添加一个元素。

Dequeue:从队首移除顶部元素,并返回该元素。

Front:查看队首元素,但不移除它。

Rear:查看队尾元素,但不移除它。

IsEmpty:检查队列是否为空。

Size:获取队列中元素的数量。

实现原理

如果我们用固定大小的数组来实现队列,优点是简单、快速。但这样不够灵活,容量一开始就定死了。如果数据太多就会溢出,太少又浪费内存。为了更灵活地管理内存,我们可以使用new []来动态分配数组空间,就像搭积木一样,需要多少就申请多少,甚至还可以自动扩容。

在下面队列CArrayQueue的实现中,我们声明了五个成员变量,分别为:m_paData、m_nCapacity、m_nFront、m_nRear、m_nCount。m_paData是一个动态分配的数组的地址,用来存储队列中的所有元素。m_nCapacity表示当前队列最多可以容纳多少个元素。m_nFront是指向队首元素的位置索引,也就是最先放入的那个元素的位置。m_nRear是指向队尾元素的位置索引,也就是最后放入的那个元素的位置。m_nCount用于记录当前队列中已有的元素数量。

cpp 复制代码
class CArrayQueue
{
public:
    CArrayQueue();
    ~CArrayQueue();

    void Enqueue(int nValue);
    int Dequeue();

    int Front();
    int Rear();

    bool IsEmpty();
    int Size();

private:
    void Resize();

private:
    int *m_paData;
    int m_nCapacity;
    int m_nFront;
    int m_nRear;
    int m_nCount;
};

Enqueue操作

进行Enqueue操作时,首先要判断当前队列是否已经满了。如果满了,则调用扩容函数Resize,将数组容量翻倍,以容纳更多元素。然后,更新队尾指针,并将新元素插入到更新后的m_nRear所指向的位置。最后,更新队列中元素的数量。

注意:由于这是一个循环队列,因此使用模运算来计算新的队尾位置。这确保了当m_nRear到达数组末尾时,可以自动绕回到数组的开头。

具体如何实现,可参考下面的示例代码。

cpp 复制代码
void CArrayQueue::Enqueue(int nValue)
{
    if (m_nCount == m_nCapacity)
    {
        Resize();
    }

    m_nRear = (m_nRear + 1) % m_nCapacity;
    m_paData[m_nRear] = nValue;
    m_nCount++;
}

Dequeue操作

进行Dequeue操作时,首先要判断当前队列是否为空。如果为空,则直接抛出异常。然后,将队首指针指向的元素返回,同时更新队首指针。最后,更新队列中元素的数量。

注意:由于这是一个循环队列,因此使用模运算来计算新的队首位置。这确保了当m_nFront到达数组末尾时,也可以自动绕回到数组的开头。

具体如何实现,可参考下面的示例代码。

cpp 复制代码
int CArrayQueue::Dequeue()
{
    if (IsEmpty())
    {
        throw underflow_error("queue is empty");
    }

    int nValue = m_paData[m_nFront];
    m_nFront = (m_nFront + 1) % m_nCapacity;
    m_nCount--;
    return nValue;
}

完整实现

Front操作、Rear操作、IsEmpty操作、Size操作都比较简单,这里就不再赘述了。CArrayQueue类的完整实现,可参考下面的示例代码。

cpp 复制代码
#include <iostream>
#include <stdexcept>

using namespace std;

class CArrayQueue
{
public:
    CArrayQueue();
    ~CArrayQueue();

    void Enqueue(int nValue);
    int Dequeue();

    int Front();
    int Rear();

    bool IsEmpty();
    int Size();

private:
    void Resize();

private:
    int *m_paData;
    int m_nCapacity;
    int m_nFront;
    int m_nRear;
    int m_nCount;
};

CArrayQueue::CArrayQueue()
{
    m_nCapacity = 2;
    m_paData = new int[m_nCapacity];
    m_nFront = 0;
    m_nRear = -1;
    m_nCount = 0;
}

CArrayQueue::~CArrayQueue()
{
    delete[] m_paData;
    m_paData = nullptr;
}

void CArrayQueue::Enqueue(int nValue)
{
    if (m_nCount == m_nCapacity)
    {
        Resize();
    }

    m_nRear = (m_nRear + 1) % m_nCapacity;
    m_paData[m_nRear] = nValue;
    m_nCount++;
}

void CArrayQueue::Resize()
{
    int nNewCapacity = m_nCapacity * 2;
    int* pNewArray = new int[nNewCapacity];
    for (int i = 0; i < m_nCount; ++i)
    {
        pNewArray[i] = m_paData[(m_nFront + i) % m_nCapacity];
    }

    delete[] m_paData;
    m_paData = pNewArray;
    m_nCapacity = nNewCapacity;
    m_nFront = 0;
    m_nRear = m_nCount - 1;
}

int CArrayQueue::Dequeue()
{
    if (IsEmpty())
    {
        throw underflow_error("queue is empty");
    }

    int nValue = m_paData[m_nFront];
    m_nFront = (m_nFront + 1) % m_nCapacity;
    m_nCount--;
    return nValue;
}

int CArrayQueue::Front()
{
    if (IsEmpty())
    {
        throw underflow_error("queue is empty");
    }

    return m_paData[m_nFront];
}

int CArrayQueue::Rear()
{
    if (IsEmpty())
    {
        throw underflow_error("queue is empty");
    }

    return m_paData[m_nRear];
}

bool CArrayQueue::IsEmpty()
{
    return m_nCount == 0;
}

int CArrayQueue::Size()
{
    return m_nCount;
}

int main()
{
    CArrayQueue q;

    q.Enqueue(66);
    q.Enqueue(77);
    q.Enqueue(88);

    cout << "Front element: " << q.Front() << endl;
    cout << "Rear element: " << q.Rear() << endl;
    cout << "Dequeued: " << q.Dequeue() << endl;
    cout << "Dequeued: " << q.Dequeue() << endl;
    cout << "Current size: " << q.Size() << endl;
    cout << "Is empty: " << (q.IsEmpty() ? "True" : "False") << endl;
    return 0;
}
相关推荐
王老师青少年编程17 分钟前
2024年信奥赛C++提高组csp-s初赛真题及答案解析(阅读程序第3题)
c++·题解·真题·csp·信奥赛·csp-s·提高组
凡人叶枫1 小时前
C++中输入、输出和文件操作详解(Linux实战版)| 从基础到项目落地,避坑指南
linux·服务器·c语言·开发语言·c++
CSDN_RTKLIB1 小时前
使用三方库头文件未使用导出符号情景
c++
傻乐u兔1 小时前
C语言进阶————指针3
c语言·开发语言
rainbow68892 小时前
Linux文件描述符与重定向原理
c++
独好紫罗兰2 小时前
对python的再认识-基于数据结构进行-a003-列表-排序
开发语言·数据结构·python
wuhen_n2 小时前
JavaScript内置数据结构
开发语言·前端·javascript·数据结构
2401_841495642 小时前
【LeetCode刷题】二叉树的层序遍历
数据结构·python·算法·leetcode·二叉树··队列
CodeSheep程序羊3 小时前
拼多多春节加班工资曝光,没几个敢给这个数的。
java·c语言·开发语言·c++·python·程序人生·职场和发展
独好紫罗兰3 小时前
对python的再认识-基于数据结构进行-a002-列表-列表推导式
开发语言·数据结构·python