关于队列的知识点以及例题讲解

news2024/11/24 11:01:00

 本篇文章将带大家学习队列的相关知识点,并且讲解几道例题,请各位小伙伴耐心观看


队列的概念

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表

遵循原则

先进先出

队列的实现

图解:

代码实现:

typedef int QDataType;
typedef struct QueuenNode
{
    struct QueuenNode* next;
    QDataType val;
}QNode;
typedef struct queue//这个结构体里存放的是next指针的头尾指针和计数器size
{
    QNode* phead;
    QNode* ptail;
    int size;//计数器
}que;
void QueueInit(que* pq);//初始化
void QueuePush(que* pq, QDataType x);//入队
void QueuePop(que* pq);//出队
int QueueSize(que* pq);
QDataType QueueFront(que* pq);//从队头进
QDataType QueueBack(que* pq);//从队尾进
void QueeuDestroy(que* pq);//销毁
bool QueueEmpty(que* pq);//判空

这里我简单提一下初始化和销毁函数里的部分代码

初始化

为什么这里需要加一个assert(pq)?

首先pq的类型是que ,而que是表示含有头尾节点的结构体,因此要判空,若pq指针为空,则报错。那么下面的代码我就不做解释了,如有新来的小伙伴可以点击👇的链接观看上一篇文章的总结内容。

销毁

//视频待补充

上一篇文章的链接:http://t.csdnimg.cn/b5hPt(含初始化与销毁的思路模板)

入队

void QueuePush(que* pq, QDataType x)
{
    assert(pq);
    QNode* newnode = (QNode*)malloc(sizeof(QNode));
    if (newnode == NULL)
    {
        perror("malloc fail");
        exit(1);
    }

//以上的部分我已经做了总结,如果有不理解的小伙伴可以去翻看上一篇的文章或者评论区留言哈


    newnode->next = NULL;//初始化
    newnode->val = x;

当我们申请完空间后要将这一部分初始化,指针部分置为空即可,而val部分直接接收x的值即可

那么👇的部分其实比较简单就是用我们先前所学过的链表的知识点


    if (pq->phead == NULL)
    {
        pq->phead = pq->ptail = newnode;
    }
    else
    {
        pq->ptail->next = newnode;//链表的尾插
        pq->ptail = newnode;//链表的尾插
    }
    pq->size++;
}

出队

void QueuePop(queue* pq)
{
    assert(pq);
    assert(pq->phead != 0);//头节点不为空
    QNode* next = pq->phead->next;
    free(pq->phead);
    pq->phead = next;
    if (pq->phead == NULL)
    {
        pq->ptail = NULL;
    }
    pq->size--;
}

思路:首先判空,注意这里除了指针pq需要判空外,pq->phead也需要判空,因为当pq->head为空时,请问下面的语句还能执行吗?相信大家仔细思考一番都能理解。

//视频讲解

从对头/队尾取

思路比较简单,除了判断指针pq不为空外还需要判断你取的对头/尾不能为空,原因:你不可能取个寂寞出来对吧,最后注意我们取的不是指针!!!是对头/尾的数值!!!当然啦这里还有一点需要注意的是这两个函数的类型是第一个结构体QueueNode中val的类型

Size函数

int QueueSize(queue* pq)
{
    assert(pq);
    return pq->size;
}

步骤:1.判空  2.返回size

判空

bool QueueEmpty(que* pq)
{

    assert(pq);
    return pq->size == 0;
}

思路:判断size是否为0,为0,则真,反之为假。


以上便是本篇文章的基础知识,接下来是例题讲解

例题讲解

例1

题意:创建两个队列实现栈

温馨提示:本题是结合了本篇文章以及上一篇文章栈的内容,用c语言写会比较复杂,请耐心观看

初始化

在已有队列的代码基础上(也就是上面我给大家讲解的基础代码),我们需要创建一个结构体里面包含两个队列,如下:

typedef struct {

    // 创建两个队列

    Queue q1;

    Queue q2;

} MyStack;

之后便是初始化,写到初始化的时候,可能会有小伙伴感到疑惑,不知在这里如何下笔。那么这里教大家一个小技巧:结构体是需要使用->或 "  .   "(点)来解引用。

技巧解释:->:通常要使用结构体指针来访问结构体成员,而点则是结构体名通过点访问结构体成员

那么,我们这里就是用结构体指针来访问结构体成员。

当我们使用c语言写这道题的时候,题目的解答区是这样的,

因此,我们需要先把上面写的队列代码cv进这个答题区。

在结构体中创建好队列,由于上面已经创好了,因此这里也就不再重复写了,那么我们回到初始化环节,刚刚说到需要用结构体指针来访问成员,但是在这里我们需要创建一个结构体指针,由于这里的初始化与以往有些不一样,因此我会带大家写完。

这里也顺便说一下,也许会有小伙伴说也可以直接创建临时变量来解决,但是临时变量它只能在该函数里使用,无法跳越到其他函数中使用,也许还有小伙伴会说直接创建全局变量,这个想法也是不太行的,有可能会导致程序出现错误。

创建结构体指针:用结构体名*  指针名 = (类型强转)malloc(sizeof(类型));

之后就是对q1和q2进行初始化,初始化结束后,有的小伙伴们就直接开始写下一个函数的代码语句了。

那么我们来思考一下这代码有没有问题,在之前的一篇文章中我有介绍过非void类型的函数都是有返回值的,即便是这个以结构体指针为类型的也是一样的。

那么,这里到底是返回上面呢,我们仔细想一下这个函数是干啥来着?是因为要初始化结构体,然后创键了结构体指针对吧,那么创建并初始化好的结构体指针就是我们所要返回的东西呀,所以这里我们直接返回所创建好的结构体指针。

那么讲完这后可能有小伙伴就直接写成了如下情况,

我们来重新审题,题目要求用队列实现栈,因此我们不能自己去给它初始化而是要放入自己一开始已经写好的队列程序里初始化,当然啦也不能忘记我们传的是地址哦。正确写法如下

入栈

思路:此时,我们两个队列都为空,因此我们随便选择一个队列,若队为空则差队1反正则插队2.

写法如下:

移除并返回栈顶元素

栈的性质:删除栈顶的数据

目标:我们要将非空队的数据导入空的队里。

思路:那么问题来了q1和q2谁空呢?这里我们没法判断,因此我们用假设法,假设q1为空,q2不为空,则将非空的那个队的前n-1个数据导入进空的队,那么剩下的就是栈顶数据了,也就是我们要出栈的数据了,这里我们需要使用循环,并且条件是当size>1时就将数据导进空队中,当只剩下

一个数据时存入临时变量top中并返回top,代码如下:

返回栈顶元素

思路这里我们使用非空队的队尾取元素并返回即可

判空

销毁

基本思路和我之前讲的一样,但这里不能直接free(obj),因为在obj这个指针里还有两个队列因此我们要先销毁队列,再释放obj。


例题2

题目要求:用两个栈实现队列

前置条件:在力扣上用c语言写这题的时候没有栈因此需要用我们自己之前写的栈

结构体指针创建

typedef struct {

    Stack pushst;

    Stack popst;

} MyQueue;

初始化

由题意可知,这题与上面一样,我们需要先创建一个结构体,并且包含两个栈的指针。

那么,我们在力扣里面写代码时,答题区是这样的。

因此,和上一题一样,我们也需要创建一个指针方便我们去调用这两个栈,创建好后我们需要将其初始化并且返回这个结构体指针 。

将元素推到队列的末尾

使用我们先前写好的入栈函数将x推到队列的末尾,正确代码如下:

思路

20240530_172421

正确写法:

从队列的开头移除并返回元素

思路:我们先将上一个函数返回的StackTop的值存放于新创建的front变量中,再删除掉所取出来的数据,最后返回front即可

判空部分

这里,我们只需要判断两个栈是否都为空,若一个为空或者两个都是空,则返回true,反之,则返回false

销毁部分

与例题一的销毁部分一样的思路

正确写法已经给大家放在上面了,大家可以参考一下。


例题3

题目要求:设计循环队列的实现

这里呢有两种思路,分别是链表和数组,由于博主即将期末考试,因此本篇文章就先给大家讲解数组的思路,至于链表的思路,大家也不必担心,等博主期末考完就给大家补上哈。

思路(数组法):

20240606_184844

因此,tail应该指向队尾的下一个指针

那么源代码如下:

typedef struct {

    int* a;

    int head;

    int tail;

    int k;//个数

} MyCircularQueue;


 

MyCircularQueue* myCircularQueueCreate(int k) {

    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));

    obj->a = (int*)malloc(sizeof(int)*(k+1));

    obj->head = 0;

    obj->tail = 0;

    obj->k = k;

    return obj;

}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {

     return obj->head == obj->tail;

}

bool myCircularQueueIsFull(MyCircularQueue* obj) {

       return (obj->tail+1) % (obj->k+1) == obj->head;

}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)

{

   if(myCircularQueueIsFull(obj))

   {

       return false;

   }

   obj->a[obj->tail] = value;

   obj->tail++;

   obj->tail %= (obj->k+1);

   return true;

}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {

     if(myCircularQueueIsEmpty(obj))

    return false;

    ++obj->head;

    obj->head %= (obj->k+1);

    return true;

}

int myCircularQueueFront(MyCircularQueue* obj) {

     if(myCircularQueueIsEmpty(obj))

         return -1;

    else

      return obj->a[obj->head];

}

int myCircularQueueRear(MyCircularQueue* obj) {

    if(myCircularQueueIsEmpty(obj))

     return -1;

    else

     return  obj->a[(obj->tail + obj->k) %(obj->k + 1)];

}

void myCircularQueueFree(MyCircularQueue* obj) {

    free(obj->a);

    free(obj);

}


那么本期视频就先到这里啦,如有疑惑的地方可以在评论区留言,最后也祝各位大学生期末不挂科,我们下期见,拜拜

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1796226.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

性能监控工具

性能是任何一款软件都需要关注的重要指标。除了软件的基本功 能,性能可以说是评价软件优劣的最重要的指标之一。我们该如何有 效地监控和诊断性能问题呢?本章基于实践,着重介绍一些针对系统 和Java虚拟机的监控和诊断工具,以帮助读者在实际开…

软件测试——蓝桥杯笔记(自用)

Before和BeforeClass,在测试前,初始化Driver,BeforeClass适用于静态方法 After和AfterClass,在测试后,关闭Driver,AfterClass适用于静态方法 自动化测试记得使用BeforeClass,AfterClass 单元…

Linux应用 sqlite3编程

1、概念 SQLite3是一个轻量级的、自包含的、基于文件的数据库管理系统,常用于移动设备、嵌入式设备和小型应用程序中,应用场景如下: 移动应用程序:由于SQLite3是零配置、无服务器的数据库引擎,非常适合用于移动应用程…

【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)

导航: 本文一些内容需要聚簇索引、非聚簇索引、B树、覆盖索引、索引下推等前置概念,虽然本文有简单回顾,但详细可以参考下文的【MySQL高级篇】 【Java笔记踩坑汇总】Java基础进阶JavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成…

[Cesium]加载GeoJSON并自定义设置符号(以点要素为例)

数据准备: Geoserver发布WFS(Web Feature Service)服务 [GeoServer系列]Shapefile数据发布-CSDN博客 数据加载: 数据准备第二种方式加载数据,利用for循环加载多个图层。首先将获取数据(每获取一次获得pomise,将其加入…

SQL优化系列-快速学会分析SQL执行效率(下)

1 show profile 分析慢查询 有时需要确定 SQL 到底慢在哪个环节,此时 explain 可能不好确定。在 MySQL 数据库中,通过 profile,能够更清楚地了解 SQL 执行过程的资源使用情况,能让我们知道到底慢在哪个环节。 知识扩展&#xff1…

Wireshark 如何查找包含特定数据的数据帧

1、查找包含特定 string 的数据帧 使用如下指令: 双引号中所要查找的字符串 frame contains "xxx" 查找字符串 “heartbeat” 示例: 2、查找包含特定16进制的数据帧 使用如下指令: TCP:在TCP流中查找 tcp contai…

汽车分销商文件流转优化:实现稳定高效的文件分发处理

在汽车圈里,分销商可是个不可或缺的角色。他们既要跟汽车厂家紧紧绑在一起,还得跟下游的销售渠道或者直接跟消费者打成一片,文件来回传递那是家常便饭。 这文件发放的速度快不快,安不安全,直接影响到分销商做事的效率…

容器(Docker)安装

centos安装Docker sudo yum remove docker* sudo yum install -y yum-utils#配置docker的yum地址 sudo yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo#安装指定版本 - 可以根据实际安装版本 sudo yum install -y docke…

Centos 报错 One of the configured repositories failed

目录预览 一、问题描述二、原因分析三、解决方案四、参考链接 一、问题描述 使用yum update更新命令就出现下面问题,系统是刚安装的,然后修改了一下IP变成手动。(排查问题前,先回顾自己做了哪些操作,方便进一步排错&a…

策略模式的理解和运用

在之前的小游戏项目中,处理websocket长连接请求的时候,需要根据传递数据包的不同类型,进行不同的处理。为了实现这个场景,比较简单的方法就是使用if-else或者switch-case语句,根据条件进行判断。但是这导致了项目代码复…

梦幻西游外网架设教程-端游篇

《梦幻西游》是一款由中国网易公司自行开发并营运的网络国产游戏。游戏以著名的章回小说《西游记》故事为背景,透过Q版的人物,试图营造出浪漫的网络游戏风格。 《梦幻西游》拥有注册用户超过3.1亿,一共开设收费服务器达472组,最高…

Sigmoid图像

import matplotlib.pyplot as plt import numpy as npdef sigmoid(x):# 直接返回sigmoid函数return 1. / (1. np.exp((0.7 -(x))/0.075))def plot_sigmoid():# param:起点,终点,间距x np.arange(0, 1, 1 / 16000)y sigmoid(x)plt.plot(x, y)plt.show…

【WP】猿人学_19_乌拉乌拉乌拉

https://match.yuanrenxue.cn/match/19 发包测试 经过发包测试,并没有携带加密参数,但是使用python无法复现,requests,httpx以及异步都不行,网上搜索了一下,这是使用了JA3指纹。可能是我做的时间比较晚&…

【iOS】UI学习——导航控制器、分栏控制器

UI学习(三) 导航控制器导航控制器基础导航控制器切换导航栏和工具栏 分栏控制器分栏控制器基础分栏控制器高级 导航控制器 导航控制器负责控制导航栏(navigationBar),导航栏上的按钮叫UINavigationItem(导航…

【论文阅读】SELF-RAG,让模型决策和反思检索

关于LLM何时使用RAG的问题,原本是阅读了关于ADAPT-LLM模型的那篇论文,被问到与SELF-RAG有何区别。所以,大概看了一下SELF-RAG这篇论文,确实很像,这些基于LLM针对下游任务的模型架构和方法,本来就很像。不过…

accelerate笔记:实验跟踪

Accelerate支持七种集成的跟踪器: TensorBoardWandBCometMLAimMLFlowClearMLDVCLive要使用这些跟踪器,可以通过在 Accelerator 类的 log_with 参数中传入所选类型来实现 from accelerate import Accelerator from accelerate.utils import LoggerTypeac…

Yolo-v5模型训练速度,与GeForce的AI算力描述

1.GeForce RTX3070 Ti官网参数: GeForce RTXTM 3070 Ti 和 RTX 3070 显卡采用第 2 代 NVIDIA RTX 架构 - NVIDIA Ampere 架构。该系列产品搭载专用的第 2 代 RT Core ,第 3 代 Tensor Core、全新的 SM 多单元流处理器以及高速显存,助您在高性…

北斗RTK+UWB定位的优势

在当今科技飞速发展的时代,定位技术的应用已渗透到我们生活的方方面面。从导航、物流到无人驾驶、智能制造,精准定位技术无处不在。而北斗RTK(Real-Time Kinematic,实时动态)和UWB(Ultra-Wideband&#xff…

闭眼推荐的,新手教师工具

亲爱的老师们,尤其是那些刚踏入教育界的新手教师们,还在为如何高效管理课堂、如何制作精美的教学材料而头疼吗?让我来分享几款教育界口碑爆棚的工具。 易查分小程序 易查分是一款超级方便的成绩查询工具,一分钟就能上传成绩并生成…