一文了解队列

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、队列是什么?
  • 二、队列的实现
  • 三、功能函数的实现
    • 1.节点定义
    • 2.队列初始化
    • 3.队列销毁
    • 4.队列尾插
    • 5.队列头删
    • 6.返回队头数据
    • 7.返回队尾数据
    • 8.返回队列大小
    • 9.判空
    • 9.一些思考
  • 四、总体代码
    • 1.头文件
  • 2.测试文件
  • 总结


在这里插入图片描述

前言

队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。这里可以和栈进行对比,如果你还不知道栈那么你可以看看这篇文章链接: 一文了解栈。


一、队列是什么?

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)。
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头。
其具体结构如图所示
在这里插入图片描述

二、队列的实现

关于队列我们可以通过顺序表或双向链表或单链表来实现,但是考虑到这里需要从头部删除数据,如果使用顺序表则需要数组前移,时间复杂度高,代价高,所以我们不使用这种方法。如果使用双向链表,好像确实可以实现队列的功能,但每一个节点都需要多一个指向前一个节点的指针,会有一定消耗,所以这里我们选择单链表实现队列是比较合适的。具体实现想法如图
在这里插入图片描述

三、功能函数的实现

1.节点定义

代码如下(示例):

typedef int QDataType;
typedef struct QueueNode
{
	QDataType val;//每一个节点的数据
	struct QueueNode* next;//指向下一个节点
}QNode;

这里我们再定义一个结构体

typedef struct Queue
{
	QNode* phead;//指向头节点
	QNode* ptail;//指向尾节点
	int size;//记录队列大小
}Queue;

这里提前说一下,因为我们在下面的函数实现传参时,需要经常传入头节点和尾节点,并且为了能改变其原来的值,我们需要传入地址,就会出现一大堆的QNode** pphead这样的二级指针,书写麻烦,所以我们定义一个结构体保存这两个节点,并且定义一个size记录队列大小。可以在下文代码中理解。

2.队列初始化

代码如下(示例):

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

这里使用指针之前我们首先判断其合法性,因为这是节点还没有建立,所以我们先把头节点和尾节点置为NULL,将size置为0.

3.队列销毁

void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

这里我们先判断指针合法性,再用一个指针cur进行遍历链表,将申请的节点进行释放,最后将头节点和尾节点置NULL,将size置0即可。

4.队列尾插

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc");
		return;
	}
	newnode->next = NULL;
	newnode->val = x;
	if (pq->ptail == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}

队列只有尾插,所以这里我们就不再把申请链表节点的代码单独封装为函数。在malloc之后检查是否开辟成功,接着把新节点的next指针和val设置好后,进行一个判断,如果链表为空,则头节点和尾节点都需要指向新节点,如果链表不为空,则可以直接尾插。在这里,我们就可体验到直接在结构体中记录尾节点的方便性。

5.队列头删

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->size > 0);
	if (pq->phead == pq->ptail)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	pq->size--;
}

头删除了判断pq是否为空外,还需要判断队列是否为空。在之后的删除中也需要判断是否为一个节点,当只有一个节点时,需要头尾置空。不是一个节点时,可以直接删除。

6.返回队头数据

QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	return pq->phead->val;
}

这个代码就很好理解,先判断是否为空后,直接返回头节点数据即可。

7.返回队尾数据

QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);
	return pq->ptail->val;
}

返回队尾数据和返回队头数据逻辑一样,不再赘述。

8.返回队列大小

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

在判断完指针有效性后,可以直接返回size中记录的数据。

9.判空

bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}

判空就是判断队列的size是否为零,判断后直接返回就行,为0返回true,不为零返回false。

9.一些思考

再写代码时我们会有以下思考:

  1. 求队列元素,判空,求元素个数基本都是用一两行代码直接返回,这些接口会不会有些许多余,直接访问结构体相应成员不就好了?
  2. 为什么没有像链表一样加入查找,打印,修改等接口?

首先,我们要知道,数据结构的实现方式多种多样,那么就会出现一个问题,如果我们使用别人已经封装好的队列,我们要怎么知道这些代码具体表示什么,我们完全不知道,只有设计者才知道,因此设计者往往会将这些功能再封装成函数,供我们直接调用。而且封装成函数方便我们的维护和使用。

这是因为队列是一种限制型数据结构,其不支持随机访问,只允许在固定的两端进行插入和删除操作,不允许在其他的位置进行任何操作。因此,队列不存在查找,打印,修改等对除队头队尾之外的位置进行操作的接口,否则会破坏队列的特性。为了遵循队列的特性,我们就不实现这些接口。

四、总体代码

1.头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
#include<stdbool.h>

typedef int QDataType;
typedef struct QueueNode
{
	QDataType val;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

//队列的初始化和销毁
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);

//队列尾插
void QueuePush(Queue* pq, QDataType x);

//队列头删
void QueuePop(Queue* pq);

//返回队列首元素
QDataType QueueFront(Queue* pq);

//返回队列尾元素
QDataType QueueBack(Queue* pq);

//返回队列大小
int QueueSize(Queue* pq);

//判空
bool QueueEmpty(Queue* pq);

2.测试文件

#include"Queue.h"

int main()
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}
	printf("\n");
	return 0;
}

在这里插入图片描述


总结

以上就是今天要讲的内容,本文仅仅简单介绍了队列的使用,而队列提供了大量能使我们快速便捷地处理数据想法和逻辑。期待你的一键三连。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电脑那些可以升级的基本配置

一. 中央处理器&#xff08;CPU&#xff09;&#xff1a;&#xff08;若不是焊点的可以升级&#xff09; 1、一句话简介&#xff1a; 这是电脑的心脏&#xff0c;决定了电脑的处理能力。常见的品牌有Intel和AMD。 2、换CPU指南&#xff1a; 1) 处理器品牌&#xff1a; - 主要…

mybatis-plus代码

项目结构 config package com.example.mpdemo.config;import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerIntercept…

FPGA串口屏方案

FPGA串口屏方案 客户应用&#xff1a;应用于工业自动化、智能家电、交通轨道、数据机房、充电桩、电力医疗、国防安全、共享设备等显示领域 主要功能&#xff1a; 1.支持几十种食材工作模式 2.支持存储自定义工作模式 3.支持延时工作 4.支持保温工作 5.支持压强模式/温度模…

统信UOS 1070如何制作GHOST镜像并安装到其他设备

原文链接&#xff1a;统信UOS 1070制作GHOST镜像并安装到其他设备 Hello&#xff0c;大家好啊&#xff01;对于想要快速部署多台计算机或在硬件更换后恢复系统的用户来说&#xff0c;制作一个GHOST镜像是一种非常高效的方法。今天&#xff0c;我将介绍如何在统信UOS 1070桌面操…

边缘网关畅维通达EN6400使用测评

1. 引言 在当前快速发展的工业4.0时代&#xff0c;边缘计算已经成为了一个关键技术&#xff0c;它能够使数据处理更加接近数据源头&#xff0c;从而提高处理速度并降低响应时间。这一技术尤其在工业自动化领域显示出了极大的潜力&#xff0c;因为它能有效处理大量来自工业设备…

简单数据结构——栈和队列1(栈超全)(初始化,销毁,出栈入栈销毁实现,例题运用)

知识特点 类似数据表链表&#xff0c;在逻辑上依次存储&#xff0c;但对比顺序表和链表有所限制&#xff0c;不能随便存储 一定要先掌握顺序表的实现&#xff0c;本人博客有顺序表专栏大家可以自行查看&#xff0c;看懂顺序表专栏之后再来了解栈的实现会更容易懂。 如果还没…

Xilinx FPGA底层逻辑资源简介(1):关于LC,CLB,SLICE,LUT,FF的概念

LC&#xff1a;Logic Cell 逻辑单元 Logic Cell是Xilinx定义的一种标准&#xff0c;用于定义不同系列器件的大小。对于7系列芯片&#xff0c;通常在名字中就已经体现了LC的大小&#xff0c;在UG474中原话为&#xff1a; 对于7a75t芯片&#xff0c;LC的大小为75K&#xff0c;6输…

LangChain:简化大模型应用

LangChain 框架提供了常见用例的抽象&#xff0c;简化了大型语言模型&#xff08;LLM&#xff09;&#xff08;如 OpenAI GPT4 或 Google PaLM&#xff09;的应用。它支持 JavaScript 和 Python。 为了弄清楚为什么需要 LangChain&#xff0c;我们先来看下 LLM 的工作原理。 …

ctfshow-web入门-102

这个题我想记录一下&#xff0c;主要是这个方法属实是有点惊艳到我了。故而进行记录&#xff0c;也为了方便大家阅读理解。 看题目&#xff0c;根据题目我写一下我的分析&#xff1a; $_POST传入一个v1&#xff0c;$_GET传入一个v2&#xff0c;一个v3。 赋值符号 优先级高于…

echarts双Y轴,并实现图例等

一个Y轴时yAxis为对象 yAxis: {type: value,name: 占比(%) },两个Y轴时yAxis为数组 yAxis: [{ // 左侧的type: value,name: 占比(%),nameTextStyle: {padding: [0, 0, 10, -50]},min: 0,max: 100,splitNumber: this.splitNumber, // 设置坐标轴的分割段数interval: 20, // 标轴…

【牛客】Tokitsukaze and Average of Substring

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 前缀和。 开一个int类型的前缀和数组pre[30][N]&#xff08;pre[i][j]表示某字符转成的数字 i 在一段区间的前缀个数。因为字母表有‘a’~z…

并发编程实现

一、并行编程 1、Parallel 类 Parallel类是System.Threading.Tasks命名空间中的一个重要类&#xff0c;它提供数据并行和任务并行的高级抽象。 For和ForEach Parallel类下的For和ForEach对应着普通的循环和遍历(普通的for和foreach)&#xff0c;但执行时会尝试在多个线程上…

Blender修改器

修改器 Modifier&#xff0c;对模型进行修改&#xff0c;相当于一个函数。 修改器图标是界面右下角的扳手样式 每个修改器的顶部都有如下样式&#xff0c;从左到右分别为&#xff1a;展开/折叠&#xff0c;修改器类型&#xff0c;修改器名称&#xff0c;编辑模式按钮&#xff…

游戏辅助 -- 某游戏一键端配置

游戏一键端下载地址及安装视频&#xff1a; https://pan.quark.cn/s/e6a373d94707 ​https://pan.quark.cn/s/ef7ab0c48776 准备工作 Vmware虚拟机软件&#xff1a;用于创建和管理虚拟机。 SecureCRT&#xff1a;一款支持SSH的终端仿真程序&#xff0c;用于远程登陆服务器…

SoC系统中AXI4 AXI3兼容性及exclusive access

AXI4和AXI3是高级扩展接口&#xff08;Advanced eXtensible Interface&#xff09;的两个不同版本&#xff0c;它们都是用于SoC&#xff08;System on Chip&#xff09;设计中的总线协议&#xff0c;用于处理器和其它外设之间的高速数据传输。以下是它们之间的一些主要区别&…

vscode设置免密登录远程服务器

文章目录 1. 问题描述2. 解决方案3. 原理 1. 问题描述 当我们使用vscode的ssh连接远程服务器后&#xff0c;过一段时间后&#xff0c;总是要求登录服务器的密码。 这就导致一个麻烦就是: 无论是在公司还是在学校&#xff0c;密码往往不是自己设置的&#xff0c;所以记忆起来就…

利用BACnet分布式IO控制器优化Niagara楼宇自动化系统

在智能建筑领域&#xff0c;随着物联网技术的飞速发展&#xff0c;如何实现高效、灵活且安全的楼宇自动化控制成为了行业关注的焦点。BACnet IP分布式远程I/O模块&#xff0c;作为这一领域的创新成果&#xff0c;正逐渐成为连接智能建筑各子系统的关键桥梁&#xff0c;尤其在与…

蓝桥杯练习系统(算法训练)ALGO-946 Q神的足球赛

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 足球赛上&#xff0c;只见Q神如闪电般的速度带球时而左&#xff0c;时而右&#xff0c;时而前&#xff0c;时而后&#xff…

带你入门React

目录 前言一&#xff0c;基本配置1.1 环境搭建1.2 页面初始化渲染二&#xff0c;基础学习2.1 结构与样式开发2.2 数据展示2.3 行内样式2.4 条件渲染2.5 列表渲染2.6 点击事件 三&#xff0c;页面更新3.1 组件数据3.2 组件数据共享 总结 前言 笔者之前的工作经验都局限于Vue&am…

pandas快速使用

DataFrame介绍 Dateframe结构和列表类似&#xff0c;区别是对于DataFrame的每一列和每一行均有一个标签。例如以下数据&#xff0c; 上述数据中&#xff0c;日期作为每行的标签。a、b、c、d、e分别是每列的标签 生成连续日期数据 使用方法date_range()&#xff0c;该方法有两…