数据结构之队列

队列

  • 队列的实现与应用:基于链表的队列详解
    • 一、队列的基本概念
    • 二、基于链表的队列实现
        1. 队列初始化
        1. 队列入队
        1. 检查队列是否为空
        1. 队列出队
        1. 获取队列头部元素
        1. 获取队列尾部元素
        1. 获取队列大小
        1. 销毁队列
    • 三、总结

队列的实现与应用:基于链表的队列详解

在计算机科学中,队列是一种常见的数据结构,广泛应用于各种场景,如任务调度、事件处理等。队列遵循先进先出(FIFO)的原则,即最早进入队列的元素最先被处理。本文将详细介绍如何基于链表实现一个队列,并探讨其基本操作和应用场景。

一、队列的基本概念

队列是一种线性数据结构,它允许在队列的一端插入元素(入队),而在另一端移除元素(出队)。队列的两端分别称为队尾(rear)和队头(front)。队列的这种操作方式类似于现实生活中的排队场景,例如在银行排队等待服务。

队列的主要操作包括:

• 入队(Enqueue):在队列的尾部添加一个元素。

• 出队(Dequeue):从队列的头部移除一个元素。

• 查看队首元素(Front):获取队列头部的元素,但不移除它。

• 查看队尾元素(Back):获取队列尾部的元素,但不移除它。

• 检查队列是否为空(Empty):判断队列中是否有元素。

• 获取队列大小(Size):返回队列中元素的数量。

• 销毁队列(Destroy):释放队列占用的内存资源。

二、基于链表的队列实现

链表是一种动态数据结构,可以方便地在任意位置插入或删除节点。因此,链表是实现队列的理想选择之一。以下是基于链表的队列实现的代码示例:

1. 队列初始化

c 复制代码
void QueueInit(Queue* q)
{
    assert(q);
    q->_front = q->_rear = NULL;
}

在初始化队列时,我们将队头 _front 和队尾 _rear 指针都设置为 NULL,表示队列为空。assert 函数用于确保传入的队列指针不为空,从而避免潜在的错误。

2. 队列入队

c 复制代码
void QueuePush(Queue* q, QDataType data)
{
    QNode* newnode = (QNode*)malloc(sizeof(QNode));
    if (newnode == NULL)
    {
        exit(1);
    }
    newnode->_data = data;
    newnode->_next = NULL;
    if (q->_front == q->_rear)
    {
        q->_front = q->_rear = newnode;
    }
    else
    {
        q->_rear->_next = newnode;
        q->_rear = newnode;
    }
}

入队操作是将一个新元素插入到队列的尾部。首先,我们创建一个新节点,并为其分配内存。如果队列为空(即 _front == _rear),则新节点既是队头也是队尾;否则,将新节点链接到队尾节点的 _next,并更新队尾指针。

3. 检查队列是否为空

c 复制代码
bool QueueEmpty(Queue* q)
{
    assert(q);
    return q->_front == NULL;
}

通过检查队头指针 _front 是否为 NULL,可以判断队列是否为空。如果 _frontNULL,则队列为空;否则,队列不为空。

4. 队列出队

c 复制代码
void QueuePop(Queue* q)
{
    assert(!QueueEmpty(q));
    if (q->_front == q->_rear)
    {
        free(q->_front);
        q->_front = NULL;
    }
    else
    {
        QNode* next = q->_front->_next;
        free(q->_front);
        q->_front = next;
    }
}

出队操作是移除队列头部的元素。在执行出队操作之前,我们使用 assert 确保队列不为空。如果队列中只有一个元素(即 _front == _rear),则释放该节点,并将 _front_rear 都设置为 NULL;否则,释放队头节点,并将 _front 指向下一个节点。

5. 获取队列头部元素

c 复制代码
QDataType QueueFront(Queue* q)
{
    assert(q);
    return q->_front->_data;
}

通过访问队头节点的 _data 成员,可以获取队列头部的元素。

6. 获取队列尾部元素

c 复制代码
QDataType QueueBack(Queue* q)
{
    assert(q);
    return q->_rear->_data;
}

类似地,通过访问队尾节点的 _data 成员,可以获取队列尾部的元素。

7. 获取队列大小

c 复制代码
int QueueSize(Queue* q)
{
    int count = 0;
    QNode* pcur = q->_front;
    while (pcur)
    {
        count++;
        pcur = pcur->_next;
    }
    return count;
}

通过遍历队列的链表,统计节点的数量,可以获取队列的大小。

8. 销毁队列

c 复制代码
void QueueDestroy(Queue* q)
{
    assert(q);
    QNode* pcur = q->_front;
    while (pcur)
    {
        QNode* next = pcur->_next;
        free(pcur);
        pcur = next;
    }
    q->_front = q->_rear = NULL;
}

销毁队列时,需要释放队列中所有节点的内存,并将 _front_rear 指针都设置为 NULL

三、总结

队列是一种简单而强大的数据结构,广泛应用于各种计算机系统和应用程序中。通过基于链表的实现,我们可以方便地实现队列的基本操作,如入队、出队、获取队列头部和尾部元素、获取队列大小以及销毁队列等。队列的先进先出特性使其在任务调度、事件处理和数据缓冲等场景中发挥着重要作用。掌握队列的实现和应用,对于理解和设计高效的计算机系统和应用程序具有重要意义。

相关推荐
南玖yy4 分钟前
数据结构C语言练习(设计循环队列)
java·c语言·数据结构
butiehua02027 分钟前
Go语言常用算法实现
数据结构·算法·golang·排序算法
luckycoding16 分钟前
1631. 最小体力消耗路径
数据结构·算法·leetcode
.YY001.19 分钟前
数据结构第一轮复习--第七章查找(包含课程代码)
数据结构·算法
星星火柴93621 分钟前
数据结构:红黑树
数据结构
对方正在长头发丿30 分钟前
P1162 填涂颜色(BFS)
数据结构·c++·算法·蓝桥杯·宽度优先
菜就多练,以前是以前,现在是现在42 分钟前
Codeforces Round 1000 (Div. 2)
数据结构·c++·算法
gentle_ice1 小时前
找树左下角的值(DFS 深度优先搜索)| LeetCode 513
数据结构·算法·leetcode·深度优先
刃神太酷啦2 小时前
基础算法篇(4)(蓝桥杯常考点)—数据结构(进阶)
数据结构·c++·算法·蓝桥杯·哈希算法·蓝桥杯c++组
_extraordinary_3 小时前
笔试专题(七)
数据结构·算法·哈希算法·贪心·线性dp