数据结构 - 队列 [动画+代码注释超详解],萌新轻松上手!!!

这篇具有很好参考价值的文章主要介绍了数据结构 - 队列 [动画+代码注释超详解],萌新轻松上手!!!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一. 队列的概念

队列是一种特殊的线性表,用于存储元素,并且按照先进先出(First In First Out)的顺序进行管理,这意味着最先加入队列的元素将会是最先从队列中被移除的元素

队列的原型:只允许在一端进行插入数据的操作,在另一端进行删除数据的操作

队列的原则:队列中的元素遵循先进先出的原则 

队列的两个经典操作:

入队列:队列的插入操作叫做入队列,进行操作的一端称为队尾

出队列:队列的删除操作叫做出队列,进行操作的一端称为队头

二. 队列的结构

数据结构 - 队列 [动画+代码注释超详解],萌新轻松上手!!!,数据结构

现实中的队列

 当我们去银行取款机排队取钱的过程就是队列,我们从队尾进入,依次取钱,取完钱之后从队头离开数据结构 - 队列 [动画+代码注释超详解],萌新轻松上手!!!,数据结构

三. 队列的实现

队列的实现有两种方式

一. 用数组实现

优点

  • 快速访问:数组允许随机访问,可以快速访问任何一个元素,特别是在入队和出队操作时,可以直接通过索引来访问队头和队尾。
  • 内存连续:数组是连续内存的数据结构,这可能有助于提高缓存效率,因为连续的内存块更有可能一起被加载到CPU缓存中。

缺点

  • 固定大小:数组的大小在初始化时固定,这意味着队列的容量有一个上限。如果队列满了,就需要执行昂贵的数组扩展操作,通常涉及分配一个更大的数组并复制现有元素。
  • 空间浪费:在使用数组实现循环队列时,即使数组中还有空间,队列也可能报告已满,这是因为循环使用的逻辑问题导致的空间利用不充分。

二. 用链表实现

优点

  1. 动态大小:链表提供了动态大小的能力,队列可以根据需要增长和缩小,不存在固定的容量限制。
  2. 内存利用率高:链表只在需要时分配内存,且只为实际存储的元素分配,这减少了内存浪费。

缺点

  1. 内存分配开销:链表的每个新元素都可能需要内存分配(除非使用内存池技术),这可能比连续的内存分配(如数组)更昂贵。
  2. 访问速度慢:链表不支持随机访问,访问任何位置的元素都需要从头开始遍历,这使得某些操作比数组慢。
  3. 额外内存需求:每个链表节点需要额外的内存空间来存储指向下一个节点的指针,这增加了每个元素的内存开销。

总结:不过整体上使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。下面我将用链表的结构来实现队列

1. 初始化队列

1.1 链式结构表示队列

在使用链表实现队列的时候,定义一个节点结构QNode,为队列中的每个元素提供一个容器,使得元素能连接起来

typedef int QDataType;

typedef struct QListNode  //定义一个节点
{
	struct QListNode* pNext; //指针域
	QDataType data; //数据域
}QNode;

1.2 队列的结构

普通链表通常只需要一个头指针来访问链表的起始位置,而队列为了支持高效的入队和出队操作,需要同时维护队头和队尾两个指针,我们通常会定义一个额外的结构体,这个结构体包括了指向队头的指针和指向队尾的指针。

typedef struct Queue
{
    QNode* front; // 队头指针
    QNode* rear;  // 队尾指针
} Queue;         // 队列结构体别名

1.3 队列的初始化 

接下来就是创建一个初始化函数,对队列里的元素进行初始化

void QueueInit(Queue* q)
{
    assert(q);  // 断言队列指针q不为NULL,确保不对NULL指针进行操作,提高程序的安全性。

    q->front = NULL; // 将队列的前端指针设置为NULL,表示队列为空,即队列中没有元素。
    q->rear = NULL;  // 将队列的后端指针也设置为NULL,与队列为空的状态一致,因为没有元素可以指向。
}

2. 销毁队列

从对头开始,进行释放空间,最后让队头队尾指针置为NULL

void QueueDestory(Queue* q)
{
    assert(q);            // 断言队列指针不为空

    QNode* cur = q->front;  // 创建一个变量,从队头开始销毁队列节点
    while (cur)
    {
        QNode* next = cur->next;  // 保存当前节点的下一个节点
        free(cur);                 // 释放当前节点的内存
        cur = next;                // 移动到下一个节点
    }

    q->front = NULL;  // 将队列的头指针置为空,表示队列已被销毁
    q->rear = NULL;   // 将队列的尾指针置为空,表示队列已被销毁
}

3. 入队列

申请一个新的节点链接到尾部,然后让尾指针,指向新节点  需要注意的是:若队列中无数据,我们需要让队头和队尾都指向这个新的节点

void QueuePush(Queue* q, QDataType x)
{
    assert(q);  // 断言队列指针不为空

    QNode* newnode = (QNode*)malloc(sizeof(QNode));  // 分配新节点的内存空间
    if (newnode == NULL)
    {
        printf("malloc fail\n");  // 如果内存分配失败,打印错误信息
        exit(-1);                  // 退出程序
    }

    newnode->data = x;   // 将数据存储到新节点中
    newnode->next = NULL;  // 新节点的下一个节点指针为空

    if (q->front == NULL)  // 如果队列为空
    {
        q->front = newnode;  // 将新节点设置为队列的头节点
        q->rear = newnode;   // 将新节点设置为队列的尾节点
    }
    else
    {
        q->rear->next = newnode;  // 将新节点链接到队列尾部
        q->rear = newnode;        // 更新队列的尾节点为新节点
    }
}

4. 出队列

释放队头的节点,并将队头更新到下一个元素。需要注意的是,如果队列中只有一个数据,在释放了队头的节点之后,要让队尾和队头的指针置空

void QueuePop(Queue* q)
{
    assert(q);  // 断言以确保队列指针 'q' 不是 NULL,保证这是一个有效的指针。
    assert(!QueueEmpty(q));  // 断言以确保队列不为空,仅当队列非空时才能进行出队操作。

    // 如果队列中只有一个节点,即队首和队尾是同一个节点
    if (q->front->next == NULL)
    {
        q->front = NULL;  // 将队首指针置为空
        q->rear = NULL;   // 将队尾指针置为空,因为队列要变为空队列
    }
    else
    {
        // 如果队列中不止一个节点,则将队首节点出队
        QNode* head = q->front->next;  // 临时保存新的队首节点
        free(q->front);  // 释放当前的队首节点的内存
        q->front = head;  // 更新队首指针为新的队首节点
    }
}

5. 获取队列的队头元素

返回队头指针指向的数据即可

QDataType QueueFront(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));//检测队列是否为空

	return q->front->data;//返回队头指针指向的数据
}

6.获取队列的队尾元素

返回队尾指针指向的数据即可

QDataType QueueBack(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));//检测队列是否为空

	return q->rear->data;//返回队尾指针指向的数据
}

7. 检测队列是否为空

判断队头的指针是否指向空

bool QueueEmpty(Queue* q)
{
	assert(q);
	return q->front == NULL;
}

8. 获取队列中有效元素个数

队列中有效元素个数,即队列中的结点个数。我们只需遍历队列,统计队列中的节点数并返回即可

int QueueSize(Queue* q)
{
    assert(q);  // 断言以确保队列指针 'q' 不是 NULL,保证这是一个有效的指针。

    QNode* cur = q->front;  // 创建一个指针 'cur',用来遍历队列,从队首开始
    int count = 0;  // 初始化计数器 'count',用于统计队列中的元素数量

    // 遍历队列,直到 'cur' 指针为空,即到达队列末尾
    while (cur)
    {
        count++;  // 对每个节点进行计数
        cur = cur->next;  // 将 'cur' 指针移动到下一个节点
    }
    
    return count;  // 返回队列中的元素总数
}

"Yesterday is history, tomorrow is a mystery, but today is a gift. That is why it is called the present."

昨日已成历史,明天充满未知,而今天是一份礼物,这就是为什么它被称为‘现在’。文章来源地址https://www.toymoban.com/news/detail-860377.html

到了这里,关于数据结构 - 队列 [动画+代码注释超详解],萌新轻松上手!!!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】详解环形队列

    队列的操作算法是笔试面试中较为常见的题目。 本文将着重介绍平时面试中常见的关于队列的应用题目,马上要进行秋招了。希望对你们有帮助 _😀 设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以

    2024年02月10日
    浏览(37)
  • 【数据结构】队列详解

    ☃️个人主页:fighting小泽 🌸作者简介:目前正在学习C语言和数据结构 🌼博客专栏:数据结构 🏵️欢迎关注:评论👊🏻点赞👍🏻留言💪🏻 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)的特性。

    2024年02月05日
    浏览(34)
  • 数据结构之队列的详解

    队列是一种先入先出(FIFO)的线性表数据结构 添加和删除操作只在表的两端进行,一端为队头,另一端为队尾 添加操作在队尾进行,称为入队或进队,删除操作在队头进行,称为出队 队列的图示 java内部的api 可以使用数组或链表实现队列 使用数组实现时,需要维护两个指针front和rea

    2024年02月03日
    浏览(35)
  • 数据结构:队列Queue详解

    队列 :只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。进行插入操作的一端称为 队尾 ,删除操作的一端称 队头 。 入队列 :进行插入操作的一端称为 队尾 。 出队列 :进行删除操作的一端称为 队头 。 在 Java 中, Queue是个接口,底层是通过链表

    2024年02月11日
    浏览(38)
  • 数据结构——优先队列c++详解

    百度百科定义 优先队列是0个或多个元素的集合,每个元素都有一个优先权或值,对优先队列执行的操作有1) 查找;2) 插入一个新元素;3) 删除.在最小优先队列(min priority queue)中,查找操作用来搜索优先权最小的元素,删除操作用来删除该元素;对于最大优先队列(max priority queue),查找操

    2024年02月09日
    浏览(40)
  • C++数据结构之队列详解

    队头填充进四个元素 此时思考一个问题,当删除元素时(元素出队列时)会出现假饱和的情况,如上图m_data[0]和m_data[1]再进行出队列操作之后,这两个位置可以容纳新的元素,但m_rear没有回到原本的m_data[0]位置,因此需要引入一个新的队列结构,环形队列,m_rear这个位置可以

    2024年02月05日
    浏览(41)
  • 数据结构之队列详解(包含例题)

    队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。 我们可以用 单链表模拟 实现顺序队列。 队列采

    2024年02月13日
    浏览(42)
  • 【数据结构】C语言队列(详解)

    前言: 💥🎈个人主页:​​​​​​Dream_Chaser~ 🎈💥 ✨✨专栏:http://t.csdn.cn/oXkBa ⛳⛳本篇内容:c语言数据结构--C语言实现队列 目录 一.队列概念及结构 1.1队列的概念 1.2队列的结构 二.队列的实现 2.1头文件 2.2链式队列的结构定义 2.3队列接口的定义 2.4初始化队列 2.5判断队列

    2024年02月10日
    浏览(44)
  • 【“栈、队列”的应用】408数据结构代码

    王道数据结构强化课——【“栈、队列”的应用】代码,持续更新

    2024年02月07日
    浏览(42)
  • 【数据结构】队列(Queue)的实现 -- 详解

    1、概念 队列 :只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有 先进先出 FIFO(First In First Out)。 入队列 :进行 插入 操作的一端称为 队尾 。 出队列 :进行 删除 操作的一端称为 队头 。 2、结构 (1)队列的顺序存储结构 入队 ,不需要

    2024年02月15日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包