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

概述

在前一篇文章中,我们已经用数组实现了队列。在本篇文章中,我们将使用链表来实现队列。使用链表的优点是:动态增长,扩容时更加平滑。缺点是:略微复杂,需要额外管理所有节点。队列相关的操作,仍然是下面6个接口。

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

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

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

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

IsEmpty:检查队列是否为空。

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

实现原理

我们使用一个带头指针和尾指针的单链表来实现队列。其中,头指针对应链表的头部,尾指针对应链表的尾部。入队操作在尾部插入新节点,出队操作从头部删除节点。所有操作均维护头指针和尾指针的正确性,确保队列行为符合FIFO规则。

在下面队列CLinkedListQueue的实现中,我们声明了两个成员变量m_pFront和m_pRear。m_pFront代表队首,m_pRear代表队尾。

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

    void Enqueue(int nValue);
    int Dequeue();
    int Front();
    int Rear();
    bool IsEmpty();
    int Size();

private:
    struct Node
    {
        int nData;
        Node* pNext;
    };

    Node* m_pFront;
    Node* m_pRear;
};

Enqueue操作

入队就是在链表的尾部插入一个新节点,详细步骤如下。

1、创建一个新节点。

2、如果队列为空,将m_pFront和m_pRear都指向新节点。

3、如果队列非空,将当前尾节点m_pRear的pNext指向新节点pNode,并更新尾指针为pNode。

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

cpp 复制代码
void CLinkedListQueue::Enqueue(int nValue)
{
    Node* pNode = new Node();
    pNode->nData = nValue;
    pNode->pNext = NULL;

    if (IsEmpty())
    {
        m_pFront = m_pRear = pNode;
    }
    else
    {
        m_pRear->pNext = pNode;
        m_pRear = pNode;
    }
}

Dequeue操作

出对就是删除链表头部节点,并返回其值,详细步骤如下。

1、如果队列为空,抛出异常。

2、取出队首节点的值,保存为临时变量。

3、将队首指针更新为下移一位后的指针,如果新的队首指针为空,则将队尾指针也设置为空。

4、释放旧节点的内存。

5、返回上面的临时变量。

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

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

    Node* pTemp = m_pFront;
    int nValue = pTemp->nData;

    m_pFront = m_pFront->pNext;
    if (m_pFront == NULL)
    {
        m_pRear = NULL;
    }

    delete pTemp;
    return nValue;
}

完整实现

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

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

using namespace std;

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

    void Enqueue(int nValue);
    int Dequeue();
    int Front();
    int Rear();
    bool IsEmpty();
    int Size();

private:
    struct Node
    {
        int nData;
        Node* pNext;
    };

    Node* m_pFront;
    Node* m_pRear;
};

CLinkedListQueue::CLinkedListQueue() : m_pFront(NULL), m_pRear(NULL)
{
    NULL;
}

CLinkedListQueue::~CLinkedListQueue()
{
    while (!IsEmpty())
    {
        Dequeue();
    }
}

void CLinkedListQueue::Enqueue(int nValue)
{
    Node* pNode = new Node();
    pNode->nData = nValue;
    pNode->pNext = NULL;

    if (IsEmpty())
    {
        m_pFront = m_pRear = pNode;
    }
    else
    {
        m_pRear->pNext = pNode;
        m_pRear = pNode;
    }
}

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

    Node* pTemp = m_pFront;
    int nValue = pTemp->nData;

    m_pFront = m_pFront->pNext;
    if (m_pFront == NULL)
    {
        m_pRear = NULL;
    }

    delete pTemp;
    return nValue;
}

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

    return m_pFront->nData;
}

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

    return m_pRear->nData;
}

bool CLinkedListQueue::IsEmpty()
{
    return m_pFront == NULL;
}

int CLinkedListQueue::Size()
{
    int nSize = 0;
    Node* pTemp = m_pFront;
    while (pTemp != NULL)
    {
        ++nSize;
        pTemp = pTemp->pNext;
    }

    return nSize;
}

int main()
{
    CLinkedListQueue q;

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

    cout << "Front element: " << q.Front() << endl;
    cout << "Rear element: " << q.Rear() << endl;
    cout << "Dequeue: " << q.Dequeue() << endl;
    cout << "Dequeue: " << q.Dequeue() << endl;
    cout << "Current size: " << q.Size() << endl;
    cout << "Is empty: " << (q.IsEmpty() ? "True" : "False") << endl;
    return 0;
}
相关推荐
炸膛坦客15 小时前
单片机/C/C++八股:(二十六)IIC 专题(I²C)---- 上集
c语言·c++·单片机
旖-旎15 小时前
LeetCode 518:零钱兑换||(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题
Henry Zhu12316 小时前
C++中的特殊成员函数与智能指针
c++
_wyt00118 小时前
多重背包问题详解
c++·背包dp
Ljwuhe19 小时前
C++——多态
开发语言·c++
延凡科技19 小时前
多场景落地复盘:端边云架构无人机智能巡检系统设计与实践
大数据·数据结构·人工智能·科技·架构·无人机·能源
越甲八千19 小时前
STL stack为何没有迭代器
c++
从零开始的代码生活_21 小时前
C++ 继承详解:访问控制、对象模型、菱形继承与设计取舍
开发语言·c++·后端·学习·算法
云小逸21 小时前
【C++ 第七阶段:模板、泛型编程与工程综合详解】
开发语言·c++
GIS阵地1 天前
QgsSingleBandPseudoColorRenderer 完整详解(QGIS 3.40.13 C++)
开发语言·前端·c++·qt·qgis