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

队列的定义

队列(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.mfbz.cn/a/573872.html

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

相关文章

接口自动化测试框架建设的经验与教训

为什么选择这个话题? 一是发现很多“点工”在转型迷茫期都会问一些自动化测试相关的问题,可以说自动化测试是“点工”升级的必经之路;二是Google一下接口自动化测试,你会发现很多自动化测试框架相关的文章,但是大部分…

Nodejs--异步编程

异步编程 函数式编程 高阶函数 在通常的语言中,函数的参数只接受基本的数据类型或者是对象引用,返回值只能是基本数据类型和对象引用。 function foo(x) {return x }高阶函数是把函数作为参数,将函数作为返回值的函数 function foo(x) {…

Oceanbase体验之(二)Oceanbase集群的搭建(社区版4.2.2)

资源规划 3台observer CPU:4C及以上 内存:32G及以上 硬盘操作系统500G 存储盘1T及以上 虚拟机可以直接划分,物理机需要提前规划好资源 一、上传oceanbase安装包 登录ocp选择软件包管理 上传Oceanbase软件包(软件包获取路径 官网免费下载社…

JavaWeb--04YApi,Vue-cli脚手架Node.js环境搭建,创建第一个Vue项目

04 1 Yapi2 Vue-cli脚手架Node.js环境搭建配置npm的全局安装路径 3 创建项目(这个看下一篇文章吧) 1 Yapi 前后端分离中的重要枢纽"接口文档",以下一款为Yapi的接口文档 介绍:YApi 是高效、易用、功能强大的 api 管理平台&#…

Hive主要介绍

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

递归排列枚举(c++)

全部排列问题 输入 n 输出 1…n 个数的全部排列。全部排列中,数字可以重复 。 例如 输入 3 输出全部排列的结果如下:111、112、113、121、122、123、131、132、133、211、212、213、221、222、223、231、232、233、311、312、313、321、322、323、33…

4.18.2 EfficientViT:具有级联组注意力的内存高效Vision Transformer

现有Transformer模型的速度通常受到内存低效操作的限制,尤其是MHSA(多头自注意力)中的张量整形和逐元素函数。 设计了一种具有三明治布局的新构建块,即在高效FFN(前馈)层之间使用单个内存绑定的MHSA&#x…

浅谈数据模型

1:事实表和维表的概述 前言:数据仓库是一种用于存储和管理大量数据的技术。其中,事实表和维表是数据仓库中的两个重要概念,首先了解一下事实表和维度表 1.事实表:是指用于存储测量“事实数据”的表,事实数…

Unity 异常 bug

OverlapBoxNonAlloc 使用bug 环境: Unity2021.3.15 在测试场景中使用 OverlapBoxNonAlloc 测试检测没有问题 但是到了真实应用场景,使用 OverlapBoxNonAlloc 检测移动中的小怪 小怪碰撞体为:带有 Rigidbody 的Circle Collider 2D 就会出现异…

Java虚拟机(jvm)常见问题总结

1.电脑怎样认识我们编写的Java代码 首先先了解电脑是二进制的系统,他只认识 01010101比如我们经常要编写 HelloWord.java 电脑是怎么认识运行的HelloWord.java是我们程序员编写的,我们人可以认识,但是电脑不认识 Java文件编译的过程 1. 程…

代码随想录(番外)图论3|1020. 飞地的数量|130. 被围绕的区域

代码随想录&#xff08;番外&#xff09;图论3|1020. 飞地的数量|130. 被围绕的区域 1020. 飞地的数量 class Solution { public:int dir[4][2]{0,1,1,0,0,-1,-1,0};int count;void dfs(vector<vector<int>>& grid,int x,int y){grid[x][y]0;count;for(int i…

大数据开发详解

点击下载《大数据开发详解》 1. 前言 随着信息化时代的快速发展&#xff0c;大数据已经成为了企业和组织不可或缺的重要资源。大数据开发则是指通过一系列技术手段&#xff0c;对海量数据进行收集、存储、处理、分析和挖掘&#xff0c;以实现数据的价值化利用。大数据开发涉及…

哈希表练习题

前言 本次博客将要写一写&#xff0c;哈希表的一些使用 哈希表主要是一个映射&#xff0c;比如数组就是一个哈希表 是一个整型对应另一个整型&#xff0c;介绍的哈希表还是要以写题目为例 第一题 242. 有效的字母异位词 - 力扣&#xff08;LeetCode&#xff09; 直接来看…

C# 给图片添加文字水印

目录 应用场景 开发运行环境 方法说明 方法代码 调用示例 小结 应用场景 在某些应用项目&#xff08;如电子档案信息管理&#xff09;中&#xff0c;查看电子图片信息是经常使用到的功能&#xff0c;此时我们就需要给显示在浏览器中的图片添加文字水印版权或提示信息。…

Java面试八股之Java中==和equals()的区别

Java中和equals()的区别 操作符&#xff1a; 对于基本数据类型&#xff08;如int、char、boolean等&#xff09;&#xff0c;比较的是它们的值是否相等。 对于对象引用类型&#xff0c;比较的是两个对象的内存地址&#xff08;即是否指向同一个对象实例&#xff09;。也就是…

Jetbrains Fleet这十个快捷键,效率提高50倍

当我们无法解决一段感情中的问题 就会选择解决这段感情 如果真诚不得到回应 那么再热情的人 也会沉默 很多人对你感兴趣 却没有人执着于你 我们知道任何一款牛批的IDE 都是有很多快捷键的,但是我们没有superpower ,不能记住所有的快捷键。 所以下面就总结了使用fleet 过…

电磁兼容(EMC):静电放电(ESD)抗扰度试验深度解读(七)

目录 1. 第一步 确定电磁环境 2. 第二步 确认设备工作状态 3. 第三步 制定试验计划 4. 间接施加的放电 4.1 水平耦合板 4.2 垂直耦合板 静电抗扰度的试验测试细节对测试结果影响比较大&#xff0c;本文详细介绍静电抗扰度试验的测试程序和注意事项。 1. 第一步 确定电磁…

PostgreSQL的学习心得和知识总结(一百三十九)|深入理解PostgreSQL数据库GUC参数 allow_alter_system 的使用和原理

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

【学习】​CSMM和CMMI的关系你了解吗

CMMI和CSMM都是评估和提升软件组织能力成熟度的模型&#xff0c;但它们在起源、应用范围、模型结构和实施目的等方面存在一些区别。在当今竞争激烈的软件市场中&#xff0c;提升软件能力成为了多数组织追求成功的关键因素。而选择适合的体系标准能够助力企业发展得更加迅速。作…

企业实施定制鞋厂ERP软件需要注意哪些问题?

企业实施定制鞋厂ERP软件是个复杂的管理系统工程&#xff0c;为了成功地为企业定制实施ERP软件&#xff0c;需要注意和解决几个关键的问题&#xff1a; . 确立ERP系统实施和定制的决策者&#xff1b;. 做好前期咨询与调研工作&#xff1b;. 做好系统产品或项目迭代规划&#x…