队列的实现(c语言实现)

news2025/1/11 5:48:20

队列的定义

队列(Queue)是一种特殊的线性数据结构,它遵循先进先出(FIFO,First In First Out)的原则。这意味着最早被添加到队列中的元素将是最先被移除的元素。队列的主要操作包括入队(enqueue,在队列的尾部添加元素)和出队(dequeue,从队列的头部移除元素)。

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

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

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

队列的实现方式

队列的实现方式有多种,包括基于数组(或循环数组)的实现、基于链表的实现等。

基于数组(或循环数组)的队列实现

这种实现方式使用一个固定大小或循环使用的数组来存储队列中的元素。数组的一个端点被视作队列的头部(front),用于执行出队操作;另一个端点被视作队列的尾部(rear),用于执行入队操作。当队列满时,需要判断是否有空间可以循环利用(即队头元素是否已被移除)。

基于链表的队列实现

基于链表的实现使用链表数据结构来存储队列中的元素。链表的头部被视作队列的头部(front),用于执行出队操作;链表的尾部被视作队列的尾部(rear),用于执行入队操作。这种实现方式更加灵活,因为链表不需要预先分配固定大小的空间,而且可以动态地扩展和收缩。

无论是基于数组还是基于链表的实现,队列都保持了其先进先出的特性,使得它在处理需要按顺序处理的元素序列时非常有用。

初始化队列

首先我们需要创建一个结点类型,类型包含了该结点的数据和指向下一结点的指针。

typedef int QDataType;//队列中存储的元素类型(这里用整型举例)

typedef struct QListNode
{
    struct QListNode* next;//指针域
    QDataType data;//数据域
}QListNode;

队列与普通链表又有所不同,普通链表只需要知道链表的头指针,而队列的信息包括了队头和队尾,所以我们需要再创建一个结构体用于存放队列的队头和队尾。

typedef struct Queue
{
    QListNode* head;//队头
    QListNode* tail;//队尾
}Queue;

队列的基本操作

我们可以先看下面这一系列操作

typedef char QDatatype;

typedef struct QueueNode
{
	struct QueueNode* next;
	QDatatype data;
}QNode;

typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;


void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq, QDatatype x);
void QueuePop(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
QDatatype QueueFront(Queue* pq);
QDatatype QueueBack(Queue* pq);

初始化队列

// 初始化队列函数  
void QueueInit(Queue* pq)  
{  
    // 使用断言确保传入的队列指针不为空  
    assert(pq);  
  
    // 将队列的头部和尾部指针都初始化为NULL  
    // 初始化时队列为空,没有节点  
    pq->head = pq->tail = NULL;  
  
    // 将队列的大小初始化为0  
    // 队列中尚未包含任何元素  
    pq->size = 0;  
}

在这个函数中,我们首先使用assert宏来检查传入的队列指针pq是否为空。如果pq为空,assert将触发一个运行时错误,这通常用于调试以确保程序在运行时不会因为无效的指针而崩溃。

然后,我们将队列的头部和尾部指针都初始化为NULL,因为队列在初始化时是空的,没有任何节点。

最后,我们将队列的大小size初始化为0,表示队列中还没有包含任何元素。

销毁队列

// 销毁队列函数  
void QueueDestroy(Queue* pq)  
{  
    // 使用断言确保传入的队列指针不为空  
    assert(pq);  
  
    // 初始化当前节点为队列的头部节点  
    QNode* cur = pq->head;  
  
    // 循环遍历队列中的每一个节点,直到没有节点为止  
    while (cur)  
    {  
        // 保存当前节点的下一个节点的指针  
        QNode* next = cur->next;  
  
        // 释放当前节点所占用的内存  
        free(cur);  
  
        // 将当前节点移动到下一个节点,继续释放内存  
        cur = next;  
    }  
  
    // 将队列的头部和尾部指针都设置为NULL  
    // 表示队列已经被销毁,不再包含任何节点  
    pq->head = pq->tail = NULL;  
  
    // 将队列的大小设置为0  
    // 表示队列中没有元素  
    pq->size = 0;  
}

这个函数负责销毁一个队列,释放队列中所有节点所占用的内存,并将队列的头部和尾部指针以及大小重置为初始状态。

入队

// 入队操作函数  
void QueuePush(Queue* pq, QDatatype x)  
{  
    // 为新节点分配内存  
    QNode* newnode = (QNode*)malloc(sizeof(QNode));  
  
    // 检查内存分配是否成功  
    if (newnode == NULL)  
    {  
        // 如果内存分配失败,打印错误信息并返回  
        perror("malloc fail");  
        return;  
    }  
  
    // 将数据x赋值给新节点的data成员  
    newnode->data = x;  
  
    // 初始化新节点的next指针为NULL  
    newnode->next = NULL;  
  
    // 如果队列为空(即头部和尾部指针都为NULL)  
    if (pq->head == NULL)  
    {  
        // 断言确保尾部指针也为NULL(这通常是正确的,但如果不是则会导致逻辑错误)  
        assert(pq->tail == NULL);  
  
        // 将新节点设置为队列的头部和尾部节点  
        pq->head = pq->tail = newnode;  
    }  
    else  
    {  
        // 如果队列不为空,将新节点添加到队列的尾部  
        // 将当前尾部节点的next指针指向新节点  
        pq->tail->next = newnode;  
  
        // 更新尾部指针,使其指向新节点  
        pq->tail = newnode;  
    }  
  
    // 队列中的元素数量加1  
    pq->size++;  
}

这个函数用于将一个元素x添加到队列的尾部。

出队

// 出队操作函数  
void QueuePop(Queue* pq)  
{  
    // 断言确保队列指针不为空  
    assert(pq);  
  
    // 断言确保队列不为空  
    assert(pq->head != NULL);  
  
    // 如果队列中只有一个节点  
    if (pq->head->next == NULL)  
    {  
        // 释放头节点占用的内存  
        free(pq->head);  
  
        // 将头部和尾部指针都设置为NULL,表示队列为空  
        pq->head = pq->tail = NULL;  
    }  
    else  
    {  
        // 否则,队列中有多个节点  
        // 保存头节点的下一个节点的指针  
        QNode* next = pq->head->next;  
  
        // 释放头节点占用的内存  
        free(pq->head);  
  
        // 将头部指针指向原来的第二个节点  
        pq->head = next;  
    }  
  
    // 队列中的元素数量减1  
    pq->size--;  
}

获取队列中元素数量

// 获取队列大小函数  
int QueueSize(Queue* pq)  
{  
    // 断言确保队列指针不为空  
    assert(pq);  
  
    // 返回队列中的元素数量  
    return pq->size;  
}

这个函数用于获取队列中的元素数量。

检查队列是否为空

// 检查队列是否为空函数  
bool QueueEmpty(Queue* pq)  
{  
    // 断言确保队列指针不为空  
    assert(pq);  
  
    // 如果队列的大小为0,则返回true,表示队列为空  
    // 否则返回false,表示队列不为空  
    return pq->size == 0;  
}

这个函数用于检查队列是否为空。它接受一个指向队列的指针pq作为参数,并使用断言来确保这个指针是有效的。然后,它比较队列的大小(size)是否等于0。如果等于0,说明队列中没有元素,函数返回true;否则,队列中有元素,函数返回false

获取队列头部元素

// 获取队列头部元素函数  
QDatatype QueueFront(Queue* pq)  
{  
    // 断言确保队列指针不为空  
    assert(pq);  
  
    // 断言确保队列不为空  
    assert(!QueueEmpty(pq));  
  
    // 返回队列头部节点的数据  
    return pq->head->data;  
}

获取队列尾部元素 

// 获取队列尾部元素函数  
QDatatype QueueBack(Queue* pq)  
{  
    // 断言确保队列指针不为空  
    assert(pq);  
  
    // 断言确保队列不为空  
    assert(!QueueEmpty(pq));  
  
    // 返回队列尾部节点的数据  
    return pq->tail->data;  
}

这个函数用于获取队列尾部元素的值。它接受一个指向队列的指针pq作为参数,并使用断言来确保队列指针有效且队列不为空。

队列的尾部元素是队列中最后一个被加入的元素。由于队列的尾部节点可以通过tail指针直接访问,因此这个函数直接返回队列尾部节点的data成员的值。

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

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

相关文章

openGauss学习笔记-271 openGauss性能调优-TPCC性能调优测试指导-测试MOT-TPCC性能

文章目录 openGauss学习笔记-271 openGauss性能调优-TPCC性能调优测试指导-测试MOT-TPCC性能271.1 TPC-C简介271.2 系统级优化271.3 BenchmarkSQL:开源TPC-C工具271.4 运行基准271.5 结果报告 openGauss学习笔记-271 openGauss性能调优-TPCC性能调优测试指导-测试MO…

Apifox接口调试工具

1、Apifox简介 Apifox 是集 API 文档、API 调试、API Mock、API 自动化测试多项实用功能为一体的 API 管理平台,定位为 Postman Swagger Mock JMeter。旨在通过一套系统、一份数据,解决多个工具之间的数据同步问题。只需在 Apifox 中定义 API 文档&a…

【题解】牛客挑战赛 71 - A 和的期望

原题链接 https://ac.nowcoder.com/acm/problem/264714 思路分析 快速幂求逆元 费马小定理: a MOD − 1 ≡ 1 ( m o d M O D ) a^{\text{MOD}-1} \equiv 1 \pmod{MOD} aMOD−1≡1(modMOD),可以转换为 a ⋅ a MOD − 2 ≡ 1 ( m o d M O D ) ① a \cd…

部署zabbix代理服务器

一、准备环境 1.1 关闭防火墙 二、代理服务器 2.1 设置zabbix下载源 2.2 编辑resolv配置文件,加入本机IP 2.3 安装zabbix数据库 2.4 开机自启服务,mysql重定义 2.5 添加数据库用户以及zabbix数据库信息 2.6 导入数据库 2.7 编辑zabbix配置文件 vim /etc/…

【文章转载】Lance Martin的关于RAG的笔记

转载自微博黄建同学 从头开始学习 RAG,看Lance Martin的这篇笔记就行了,包含了十几篇论文和开源实现! —— 这是一组简短的(5-10 分钟视频)和笔记,解释了我最喜欢的十几篇 RAG 论文。我自己尝试实现每个想…

开源协议与商业许可:选择与遵循

文章目录 开源协议MIT许可证(MIT License)BSD许可证(BSD License)Apache许可证 2.0(Apache License 2.0)GNU宽松通用公共许可证(GNU Lesser General Public License,LGPL&#xff09…

线上论坛自动化测试

文章目录 前言一、测试用例设计二、自动化测试1.登录功能2.注册功能3.发布帖子4.删除帖子5.修改帖子6.帖子详情7.个人中心8.通过suite套件总测试 前言 对论坛项目进行测试用例编写,通过 Selenium JUnit 单元测试框架对项目的功能进行自动化测试。 论坛项目的部分…

Hive主要介绍

Hive介绍 hive是基于 Hadoop平台操作 HDFS 文件的插件工具 可以将结构化的数据文件映射为一张数据库表 可以将 HQL 语句转换为 MapReduce 程序 1.hive 是由驱动器组成,驱动器主要由4个组件组成(解析器、编译器、优化器、执行器) 2.hive本身不…

CHARLS轻松发二区,只用了COX回归模型 | CHARLS CLHLS CFPS 公共数据库周报(4.3)...

零基础CHARLS发论文,不容错过! 长期回放更新指导!适合零基础,毕业论文,赠送2011-2020年CHARLS清洗后的数据全套代码! CHARLS公共数据库 CHARLS数据库简介中国健康与养老追踪调查(China Health and Retireme…

揭秘神器:智能私信破局获客难!

在数字营销的海洋中,每个企业都如同一艘努力航行的船,希望能在广阔的客户蓝海中获得丰收。然而,现实却往往充满挑战,尤其是当面对如何吸引并维系客户这一核心难题时。传统的获客手段逐渐显得力不从心,而智能科技的介入…

项目十一:爬取热搜榜(小白实战级)

首先,恭喜各位也恭喜自已学习爬虫基础到达圆满级,今后的自已python爬虫之旅会随着网络发展而不断进步。回想起来,我学过请求库requests模块、解析库re模块、lmxl模块到数据保存的基本应用方法,这一次的学习python爬虫之旅收获很多…

三 SpringMVC返回数据以及RESTFul设计标准

SpringMVC返回数据 一 控制页面跳转 1.1 快速使用 开发模式回顾在 Web 开发中,有两种主要的开发模式:前后端分离和混合开发。前后端分离模式:[重点]指将前端的界面和后端的业务逻辑通过接口分离开发的一种方式。开发人员使用不同的技术栈和…

OAuth2、JWT

文章目录 OAuth2JWT OAuth2 官网: https://oauth.net/2/ 在 RFC 6749 中说明 1、资源所有者 resource owner, 如 github 用户 2、客户端/第三方应用 client, 如 支持github 登录的 csdn 3、资源服务器 resource server, 如 4、授…

高级美肤解决方案,精细的磨皮处理效果

在数字化时代,高清视频和精致图片已成为企业展示形象、推广产品的重要媒介。然而,面对镜头时,肌肤的微小瑕疵往往成为影响整体美观的“绊脚石”。美摄科技针对这一问题,推出了一系列基于人脸识别技术的高级美肤解决方案&#xff0…

基于昇腾AI 使用AscendCL实现垃圾分类和视频物体分类应用

现如今,人工智能迅猛发展,AI赋能产业发展的速度正在加快,“AI”的需求蜂拥而来,但AI应用快速落地的过程中仍存在很大的挑战:向下需要适配的硬件,向上需要完善的技术支持,两者缺一不可。 基于此&…

Python中ArcPy按照分幅条带与成像日期拼接每个8天间隔内的遥感影像

本文介绍基于Python中的ArcPy模块,将大量遥感影像文件按照分幅条带编号与成像时间加以分组,并将同一分幅的遥感影像加以每个8天时间间隔内的镶嵌拼接的方法。 首先,来看一下本文具体的需求。我们现有一个文件夹,其中含有大量的.ti…

网工交换基础——Qinq技术

一、Qinq的概述 QinQ(802.1Q-in-802.1Q),也叫做VLAN Stacking或Double VLAN,由IEEE 802.1ad标准定义,是一项扩展VLAN空间的技术,通过在802.1Q标签报文的基础上再增加一层802.1Q的Tag来达到扩展VLAN空间的目…

面试:JVM垃圾回收

一、三种垃圾回收算法 1、标记清除(已废弃) 找到根对象(局部变量正在引用的对象、静态变量正在引用的对象);沿着根对象的引用链,查看当前的对象是否被根对象所引用,若被引用,则加上…

Oracle数据库的AI能力分析,释放企业数据价值

解锁Oracle数据库的AI潜力 Oracle数据库提供了一系列的AI能力,旨在帮助企业和开发者更高效地利用人工智能技术。以下是Oracle数据库AI能力的一些关键点:1. AI向量相似性搜索:Oracle Database 23c引入了AI Vector Search功能,该功…

2024/4/25 C++day3

#include <iostream> using namespace std; class Person //Person类 {string name; //两个私有属性变量name&#xff0c;ageint age;public: //一个公有属性指针变量&#xff0c;一个无参构造函数&#xff0c;一个有参构造函数&#xff0c;一个sho…