数据结构之队列(源代码➕图解➕习题)

这篇具有很好参考价值的文章主要介绍了数据结构之队列(源代码➕图解➕习题)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

        在学过栈之后,会了解到栈的底层是根据顺序表或者链表来构建的,那么我们今天要学习的队列是否也是基于顺序表和链表呢?那我们直接进入正题吧!

1. 队列的概念(图解)

        还是跟上节一样,依旧用图解的方式让大家更好的理解概念。

1.1 队列的组成:

        队列:队列指的是图中黑色边框及其内部的空间

        队头:出元素的一边叫队头

        队尾:入元素的一边叫队尾

        队内元素:蓝色正方形

数据结构之队列(源代码➕图解➕习题),数据结构,数据结构

1.2 队列的进出规则:先进先出

        队列的进出规则跟栈不一样,栈是先进后出,而队列是先进先出

        队列只能从队头出,队尾入,所以这就造就了队列的先进先出,先从队尾入的元素,先从队头出。

数据结构之队列(源代码➕图解➕习题),数据结构,数据结构

数据结构之队列(源代码➕图解➕习题),数据结构,数据结构

2. 队列的架构

2.1 队列为顺序表构成(舍弃方案)

        队列的入队列相当于尾插(头插),队列的出队列相当于头删(尾删)        

        我们知道顺序表的尾插尾删是非常快的,很方便。但是头插头删却需要挪动数据,覆盖,十分麻烦。无论是我们入队列和出队列,我们都必然会涉及到头的挪动。这样大大增加了我们时间复杂度,所以我们队列不推荐使用顺序表构建。

2.2 队列为链表构成(文末源代码)

        我们是选择什么样的链表呢?单向链表还是双向链表,是否带头,是否成环?不要着急,我们先来看单链表是否简单可行。

2.2.1 队列为单链表构成

数据结构之队列(源代码➕图解➕习题),数据结构,数据结构

        如图,我们选择链表的头部作为了队头,链表的尾部作为了队尾,那么出队列就是头删,入队列就是尾插。

1. 入队列:

        入队列就是链表的尾插,先找到链表的尾,再跟新节点连接就可以了。但是当我们队列中没有元素的时候,就需要改变一下链表头指针指向的位置,让他指向第一个节点,这里我们是改变指针,需要用到二级指针,但是我们今天不用二级指针,使用一个新的方法来解决。

数据结构之队列(源代码➕图解➕习题),数据结构,数据结构

2. 出队列

        出队列相当于链表的头删,看图就可以了。        数据结构之队列(源代码➕图解➕习题),数据结构,数据结构

我们会发现其实单链表已经可以几乎很好的解决队列这个数据结构了,那我们就没有必要去创造什么带头啊,循环啊,双向啊这些结构。所以接下来就让源代码登场吧!

3. 队列由单链表构成(源代码)

3.1 队列的定义

        这里跟以往不同的点是 这里我们重新定义了一个结构体,包含了队列的头节点和尾结点,我们这么定义的目的是可以更改头节点和尾节点。

//如果你要更改队列元素的数据类型,在这里更改一次就OK了,int变成其他数据类型
typedef int QDataType; 
//这里我们正常定义队列的节点,因为是链表构成的,和链表节点一样
typedef struct QueueNode 
{
    struct QueueNode* next;
    QDataType data;
}QNode;
//这里我们重新定义了一个结构体,包含了队列的头节点和尾结点,我们这么定义的目的是可以更改头节点和尾节点
typedef struct Queue
{
    QNode* head;
    QNode* tail;
    int size;
}Que;

3.2 队列的初始化

//初始化
void QueueInit(Que* pq)
{
    assert(pq);

    pq->head = pq->tail = NULL;
    pq->size = 0;
}

3.3 队列的销毁

void QueueDestroy(Que* pq)
{
    assert(pq);

    QNode* cur = pq->head;
    while (cur)
    {
        QNode* next = cur->next;
        free(cur);
        cur = next;
    }

    pq->head = pq->tail = NULL;
    pq->size = 0;
}

3.4 入队列

//入队列
void QueuePush(Que* pq, QDataType x)
{
    assert(pq);

    QNode* newnode = (QNode*)malloc(sizeof(QNode));
    if (newnode == NULL)
    {
        perror("malloc fail");
        exit(-1);
    }

    newnode->data = x;
    newnode->next = NULL;

    if (pq->tail == NULL)
    {
        pq->head = pq->tail = newnode;
    }
    else
    {
        pq->tail->next = newnode;
        pq->tail = newnode;
    }

    pq->size++;
}

3.5 出队列

//出队列
void QueuePop(Que* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));

    if (pq->head->next == NULL)
    {
        free(pq->head);
        pq->head = pq->tail = NULL;
    }
    else
    {
        QNode* next = pq->head->next;
        free(pq->head);
        pq->head = next;
    }

    pq->size--;
}

3.6 取队头元素

//取队头元素
QDataType QueueFront(Que* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));

    return pq->head->data;
}

3.7 取队尾元素

//取队尾元素
QDataType QueueBack(Que* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));

    return pq->tail->data;
}

3.8 判断队列是否为空

bool QueueEmpty(Que* pq)
{
    assert(pq);

    return pq->head == NULL;
}

3.9 求队列长度

//队列的长度
int QueueSize(Que* pq)
{
    assert(pq);

    return pq->size;
}

4. 习题

4.1 下列关于队列的叙述错误的是( )

A.队列可以使用链表实现

B.队列是一种“先入先出”的数据结构

C.数据出队列时一定只影响尾指针

D.数据入队列时一定从尾部插入

答案:C

解析:出队操作,一定会影响头指针,如果出队之后,队列为空,会影响尾指针。

4.2  用无头单链表存储队列,其头指针指向队头结点,尾指针指向队尾结点,则在进行出队操作时()

A.仅修改队头指针

B.队头、队尾指针都要修改

C.队头、队尾指针都可能要修改

D.仅修改队尾指针

答案:C

解析:出队操作,一定会修改头指针,如果出队之后,队列为空,需要修改尾指针。

4.3 以下不是队列的基本运算的是( )

A.从队尾插入一个新元素

B.从队列中删除队尾元素

C.判断一个队列是否为空

D.读取队头元素的值

答案:B

解析:队列只能从队头删除元素。

4.4 下面关于栈和队列的说法中错误的是( )(多选)

A.队列和栈通常都使用链表实现

B.队列和栈都只能从两端插入、删除数据

C.队列和栈都不支持随机访问和随机插入

D.队列是“先入先出”,栈是“先入后出”

答案:AB

解析:

A错误:栈是尾部插入和删除,一般使用顺序表实现,队列是头部删除尾部插入,一般使用链表实现

B错误:栈是后进先出,尾部插入和删除,并不是两端;队列是先进先出,尾部插入头部删除。

4.5 下列关于顺序结构实现循环队列的说法,正确的是( )

A.循环队列的长度通常都不固定

B.直接用队头和队尾在同一个位置可以判断循环队列是否为满

C.通过设置计数的方式可以判断队列空或者满

D.循环队列是一种非线性数据结构

答案:C

解析:顺序结构实现循环队列是通过数组下标的循环来实现的

A错误:循环队列的长度都是固定的

B错误:队头和队尾在同一个位置时 队列可能是空的,也可能是满的,因此无法判断

C正确:设置计数即添加一个字段来记录队列中有效元素的个数,如果队列中有效元素个数等于空间总大小时队列满,如果队列中有效元素个数为0时队列空

D错误:循环队列也是队列的一种,是一种特殊的线性数据结构

好啦,我们关于队列的实现已经结束了,谢谢大家!文章来源地址https://www.toymoban.com/news/detail-736402.html

到了这里,关于数据结构之队列(源代码➕图解➕习题)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【数据结构】计数排序 & 排序系列所有源代码 & 复杂度分析(终章)

    目录 一,计数排序 1,基本思想 2,思路实现 3,计数排序的特性总结: 二,排序算法复杂度及稳定性分析 三,排序系列所有源代码 Sort.h Sort.c Stack.h Stack.c 计数排序也叫非比较排序; 1,基本思想 计数排序又称为 鸽巢原理 ,是对 哈希直接定址法 的变形应用 操作步骤 : 1

    2024年02月08日
    浏览(32)
  • 【数据结构】二叉树的销毁 & 二叉树系列所有源代码(终章)

    目录 一,二叉树的销毁  二,二叉树系列所有源代码 BTee.h BTee.c Queue.h Queue.c 二叉树建好了,利用完了,也该把申请的动态内存空间给释放了,那要如何释放呢? 我们还是以这棵树为例, 要把这棵树销毁掉,其实就是把树上的结点全部释放掉 ,但是呢这个 释放的顺序挺讲究

    2024年02月08日
    浏览(35)
  • 数组:矩阵快速转置 矩阵相加 三元组顺序表/三元矩阵 随机生成稀疏矩阵 压缩矩阵【C语言,数据结构】(内含源代码)

    目录 题目: 题目分析: 概要设计: 二维矩阵数据结构: 三元数组三元顺序表顺序表结构: 详细设计: 三元矩阵相加: 三元矩阵快速转置: 调试分析: 用户手册: 测试结果:  源代码: 主程序:  头文件SparseMatrix.h:  头文件Triple.h: 总结: 稀疏矩阵A,B均采用 三元组

    2023年04月26日
    浏览(52)
  • 电子凸轮应用追剪算法详细图解(附PLC完整源代码)

    谈到运动控制就离不开编码器,有关编码器测速,测距的相关内容,大家可以查看专栏的其它文章,和飞剪控制息息相关的编码器测速,请参看下面的博客,链接如下: 如何通过编码器信号计算输送线/输送带线速度(飞剪、追剪算法基础)_RXXW_Dor的博客-CSDN博客 不同品牌P

    2024年02月16日
    浏览(43)
  • 【数据结构】队列篇| 超清晰图解和详解:循环队列模拟、用栈实现队列、用队列实现栈

    博主简介: 努力学习的22级计算机科学与技术本科生一枚🌸 博主主页: @是瑶瑶子啦 每日一言🌼: 每一个不曾起舞的日子,都是对生命的辜负。——尼采 🔗622. 设计循环队列 👧🏻 思路: 🍊数据结构: 使用数组为数据结构,且采用牺牲一个空间的方法来包装判空和判满的

    2024年02月11日
    浏览(29)
  • 【高阶数据结构】AVL树详解(图解+代码)

    前面对map/multimap/set/multiset进行了简单的介绍,在其文档介绍中发现。 这几个容器有个共同点是: 其底层都是按照二叉搜索树来实现的,但是二叉搜索树有其自身的缺陷,假如往树中插入的元素有序或者接近有序,二叉搜索树就会退化成单支树,时间复杂度会退化成O(N),因此

    2024年02月13日
    浏览(36)
  • 【算法基础】数据结构| 单链表+双链表 代码实现+图解+原理

    博主简介: 努力学习的预备程序媛一枚~ 博主主页: @是瑶瑶子啦 所属专栏: Java岛冒险记【从小白到大佬之路】 因为瑶瑶子正在备战蓝桥杯和校内ACM选拔赛,最近在学习算法相关的知识。我是借助 AcWing网站 来学习的,这篇文章是我学习就我学习内容的一个笔记,其中的一些

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

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

    2024年02月07日
    浏览(34)
  • 数据结构例题代码及其讲解-栈与队列

    栈Stack 后进先出 ​ 栈的结构体定义及基本操作。 初始化 ​ 这里初始化时是将栈顶指针指向-1,有些则是指向0,因此后续入栈出栈的代码略微有点区别 判断栈是否为空 压栈操作 由于初始时栈顶指针指向-1,因此需要先变化栈顶指针,然后入栈操作; 且当MaxSize为50时候,数

    2024年02月10日
    浏览(34)
  • 【算法与数据结构】归并排序的代码实现(详细图解)以及master公式的讲解

    目录 1、归并排序  1.1、算法描述  1.2、图解说明 2、代码实现  3、master公式 3.1、公式以及结论 3.2、适用于某些特殊的递归 3.3、计算归并排序的时间复杂度 归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用 递归 或者说是 分治法 (Divide and Conquer)的一个非

    2024年02月08日
    浏览(46)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包