C语言实现“队列“

news2025/1/9 19:02:29

在这里插入图片描述

🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨
🐻推荐专栏: 🍔🍟🌯C语言进阶
🔑个人信条: 🌵知行合一
🍉本篇简介:>:分享数据结构之C语言实现"队列".各个接口分别分析,讲解思路已经动图讲解.
金句分享:
✨书要好好读,喜欢的人也要好好争取!✨

前言

目录

  • 前言
  • 一、队列
    • 1.1 队列的介绍:
    • 1.2 "队列"的常见接口:
  • 二、接口的具体实现:
    • 2.1 "队列"的"初始化"操作(QueueInit)
    • 2.2 "入队"操作(QueuePush)
    • 2.3 "队列"判空(QueueEmpty)
    • 2.4 "出队"(QueuePop)
    • 2.5 "队列"长度函数
    • 2.6 取"队头"和"队尾"元素
    • 2.7 "队列"的销毁:
  • 三、结语:
  • 四、总代码:
    • 4.1 主测试区(test.c)
    • 4.2 接口实现区(Queue.c):
    • 4.3 接口声明区(Queue.h):

一、队列

1.1 队列的介绍:

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

队列具有先进先出FIFO(First In First Out)

入队列:进行"插入"操作的一端称为队尾
出队列:进行"删除"操作的一端称为队头

在这里插入图片描述

顺序表还是用链表实现队列比较好呢?

结构尾插头插
顺序表效率很高,不需要移动数据效率极低,需要移动除首元素以外的所有数据
链表效率较低,需要遍历链表找尾巴效率高,改变头指针即可
  1. 对于链表的缺点,我们可以额外创建一个尾指针用于记录尾结点.这样效率就不是问题了,而顺序表的头插是硬伤.
  2. 链表不需要扩容,顺序表需要动态扩容/

综上,咱还是选择链表=实现队列吧!

typedef int QDatatype;

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

typedef struct Queue
{
	QNode* head;//记录队首
	QNode* tail;//记录队尾
	int size;//记录长度
}Queue;

图解:
在这里插入图片描述

1.2 "队列"的常见接口:

接口介绍:

//队列的初始化操作
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);

二、接口的具体实现:

2.1 "队列"的"初始化"操作(QueueInit)

队列的结构是由两个结点指针,加一个记录长度的size变量组成.

队列的初始状态:
头指针=尾指针,长度为0.

代码:

//初始化"队列"操作
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = NULL;
	pq->tail = NULL;
	int size = 0;
}

2.2 "入队"操作(QueuePush)

步骤:

  1. 申请一个结点,将数据域赋值为x(目标值),指针域指向NULL;
  2. 一般情况下,"入队"操作只影响尾指针.
  3. 链接:将尾指针指针域指向新节点.
  4. 更新尾指针(令尾指针本身指向新节点).

特殊情况:

第一个元素入队时,头指针尾指针都会收受到影响.需要将头指针尾指针都指向新节点.

在这里插入图片描述

特殊情况:
在这里插入图片描述

代码:

//入队列
void QueuePush(Queue* pq, QDatatype x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	newnode->data = x;
	newnode->next = NULL;
	if (pq->head == NULL)//第一个元素入队列时,会影响头指针
	{
		pq->head = pq->tail = newnode;//将头指针和尾指针都指向新节点
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;//更新队尾
	}
	pq->size++;
	return 0;
}

2.3 "队列"判空(QueueEmpty)

如果头指针和尾指针都指向NULL则表示空队列

代码:

//队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	//如果头指针和尾指针都指向NULL则表示空队列
	if (pq->head == pq->tail && pq->tail == NULL)
	{
		return true;
	}
	return false;
}

2.4 “出队”(QueuePop)

步骤:

  1. 对于删除元素的"出队"操作,我们首先要进行"判空"操作.空队列不允许删除.
  2. 创建一个结点指针(Delete ):用于记录待会要出队的原队首结点.
  3. 将队首结点向后移动一步.(即将队首指针指向第二个元素).
  4. 释放Delete 结点.
  5. 长度(size)减少1;

在这里插入图片描述

特殊情况:
剩下最后一个待出队元素时:
会影响头指针,需要将头指针和尾指针都置空NULL;

这里就不画图了,相信聪明的友友们可以理解.

代码:

//出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	QNode* Delete = pq->head;//记录原队首

	if (pq->head == pq->tail)//如果是最后一个元素出队列
	{
		pq->head = pq->tail = NULL;
	}
	else pq->head = pq->head->next;//更新队头指针
	free(Delete);//释放原队首
	pq->size--;
}

2.5 "队列"长度函数

这里采用了增加一个变量size用于记录队列的长度.所以直接返回size即可.
如果没有size就需要遍历.

//队列的长度
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

2.6 取"队头"和"队尾"元素

在创建队列时,我们已经分析了链式队列的结构,队首=和队尾元素我们可以直接通过队首指针(head)和队尾指针(tail)访问其数据域即可.

//取队头元素
QDatatype QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->head);
	return pq->head->data;
}

//取队尾元素
QDatatype QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->tail);
	return pq->tail->data;
}

2.7 "队列"的销毁:

与链表的销毁类似:
步骤:

  1. 创建两个结点指针

(1):QNode* cur:从头指针开始,遍历整个队列
(2):QNode* next:用于记录下一个结点,方便cur被释放后,继续往下遍历.

  1. 释放cur指针指向的结点.
  2. 更新cur指针和next指针.
  3. 将队首指针(head)和队尾指针(tail)指向NULL.
  4. 将size置为0;

代码:

//队列的销毁
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	QNode* next = cur;
	while (next)
	{
		next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
	pq->size = 0;
}

三、结语:

"栈"和"队列"都是很重要的一种数据结构,在计算机中有很多应用,后续会更新==“循环队列”==,和OJ题:用栈模拟队列,用队列模拟栈等.
如果文章对大家有帮助的话,牛牛会很开心的.💗💗💗

如果文章中有错误,或者不理解的地方,欢迎小伙伴们私信提意见和提问哦!互相交流学习.
最后,小伙伴们的点赞就是给牛牛最大的支持,能不能给牛牛来一个一键三连呢?谢谢支持。

在这里插入图片描述

四、总代码:

4.1 主测试区(test.c)

#include"Queue.h"
int main()
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	printf("队头数据%d\n", QueueFront(&q));
	printf("队头数据%d\n", QueueBack(&q));
	while (!QueueEmpty(&q))
	{
		printf("%d ", q.head->data);
		QueuePop(&q);
	}
	QueueDestroy(&q);;
	return 0;
}

4.2 接口实现区(Queue.c):


#include "Queue.h"

//队列的初始化操作
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = NULL;
	pq->tail = NULL;
	int size = 0;
}



//入队列
void QueuePush(Queue* pq, QDatatype x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	newnode->data = x;
	newnode->next = NULL;
	if (pq->head == NULL)//第一个元素入队列时,会影响头指针
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;//更新队尾
	}
	pq->size++;
	return 0;
}


//队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	if (pq->head == pq->tail && pq->tail == NULL)
	{
		return true;
	}
	return false;
}


//出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	QNode* Delete = pq->head;//记录原队首

	if (pq->head == pq->tail)//如果是最后一个元素出队列
	{
		pq->head = pq->tail = NULL;
	}
	else pq->head = pq->head->next;//更新队头指针
	free(Delete);//释放原队首
	pq->size--;
}

//队列的长度
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

//取队头元素
QDatatype QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->head);
	return pq->head->data;
}

//取队尾元素
QDatatype QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->tail);
	return pq->tail->data;
}


//队列的销毁
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	QNode* next = cur;
	while (next)
	{
		next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
	pq->size = 0;
}

4.3 接口声明区(Queue.h):

#pragma once

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

typedef int 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);

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

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

相关文章

回归预测 | MATLAB实现SSA-DELM和DELM麻雀算法优化深度极限学习机多输入单输出回归预测对比

回归预测 | MATLAB实现SSA-DELM和DELM麻雀算法优化深度极限学习机多输入单输出回归预测对比 目录 回归预测 | MATLAB实现SSA-DELM和DELM麻雀算法优化深度极限学习机多输入单输出回归预测对比效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 Matlab实现SSA-DELM和D…

突破极限:YOLO9000 论文解读 - 构建更好、更快、更强大的实时检测系统

YOLOv2 论文全篇完整翻译 摘要 我们介绍了YOLO9000&#xff0c;这是一种先进的、实时的目标检测系统&#xff0c;可以检测超过9000个物体类别。首先&#xff0c;我们对YOLO检测方法进行了各种改进&#xff0c;包括新颖的方法和借鉴自先前工作的方法。改进后的模型YOLOv2在标准…

港科夜闻|叶玉如校长在大湾区科学论坛主论坛发表「为应对人口老龄化贡献大湾区力量」主旨演讲...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、叶玉如校长在大湾区科学论坛主论坛发表「为应对人口老龄化贡献大湾区力量」主旨演讲。她指出&#xff0c;中国已成为世界上老年人口最多、老龄化速度最快的国家之一&#xff0c;预计到2025年&#xff0c;65岁及以上人口3…

亚马逊云科技:点燃云原生数据库创新的星星之火

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 近10年&#xff0c;全球数据库市场加速变革&#xff0c;云数据库尤其是云原生数据库成为整个数据库市场的关键变量。某种程度上&#xff0c;亚马逊云科技作为全球云原生数据库的领导者&#xff0c;具有行业风向标的价值。 近…

2023.5.19Redis和MongoDB安装

四种数据库设置 hbase(main):001:0> create student,Sname,Ssex,Sage,Sdept,course Created table student Took 2.4760 seconds > Hbase::Table - student hbase(main):002:0> list TABLE …

性能测试——系统性能数据收集和Prometheus 监控系统部署应用实战

系统性能数据收集和Prometheus 监控系统部署应用实战 一、部署性能监控工具 node-exporter1、拉取镜像2、启动容器&#xff1a;3、配置prometheus.yml4、重启prometheus系统&#xff0c;检查node-exporter targets数据是否显示正常 二、Prometheus 监控系统部署应用实战1、实战…

盘点IntelliJ IDEA 中的“快速”功能,你知道几个?

IntelliJ IDEA&#xff0c;是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的java开发工具&#xff0c;尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能是非常强大的。 Int…

HTML+CSS实训——Day02——仿一个网易云音乐的登陆界面

前言 今天要继续完成我们的音乐软件了&#xff0c;昨天写完了封面&#xff0c;今天该完成开屏广告和登陆界面了。 登陆界面代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-C…

短视频矩阵源码核心研发接口

1.短视频矩阵源码涉及了多种接口&#xff0c;包括但不限于视频上传、视频播放、视频推荐、用户管理、评论管理、点赞管理等。其中视频上传接口用于将用户上传的视频数据进行处理和存储&#xff1b;视频播放接口用于向用户展示视频内容并提供播放操作&#xff1b;视频推荐接口用…

springboot 集成 Swagger2(速通)

目录 1. 概述2. 案例 13. UI 的简单使用4. 简单配置 Docket 对象1. 配置文档的描述信息2. 定义包扫描规则 5. 指定接口不生成文档1. 自定义注解2. 路径匹配 6. 常用注解 1. 概述 简单理解——代写接口文档的框架&#xff0c;可跟随接口修改实时更新。 Open API 格式&#xff…

【服务器】安卓手机使用Termux搭建web服务

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员&#xff0c;2024届电子信息研究生 目录 概述 1.搭建apache 2.安装cpolar内网穿透 3.公网访问配置 4.固定公网地址 5.添加站点 概述 Termux是一个Android终端仿真应用程序&#xff0c;用于在 Android 手机上搭建一个…

从C语言到C++_12(string相关OJ题)(leetcode力扣)

上一篇已经讲了string类的接口函数&#xff0c;然后根据查文档刷了牛客和力扣58最后一个单词的长度&#xff0c; 还有力扣415字符串相加&#xff0c;这篇继续跟着查文档来刷力扣题&#xff0c;体会C刷题的方便。 目录 917. 仅仅反转字母 - 力扣&#xff08;LeetCode&#xf…

ESP32 智能手表软件设计,具有多个表盘、心率传感器、指南针和游戏

ESP32 智能手表 GUI 导航 整个 GUI 的设计方式使我们可以使用单个按钮浏览每个选项。我们可以使用短按和长按来浏览它们。您可以在下图中找到整个 GUI 流程。蓝线表示单击/短按,而绿线表示长按。在时间设置和设置菜单中,您可以浏览每个选项或使用短时钟归档。选择该选项并使用…

搭建简单的HTTP服务器(Nodejs) - 内网穿透公网远程访问

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 转载自cpolar内网穿透的文章&#xff1a;使用Nodejs搭建HTTP服务&#xff0c;并实现公网远程访问「内网穿透」 前言 Node.…

【工业控制系统】工业控制系统安全简介第 2 部分

介绍 Purdue Enterprise Reference Architecture (PERA)、其他参考模型和安全 ICS 架构的最佳实践。 安全 ICS 架构的 Purdue 模型和最佳实践 在本系列的第一部分中&#xff0c;我们回顾了工业控制系统 (ICS) 的独特沿袭&#xff0c;并介绍了保护 ICS 的一些挑战。在第二部分中…

初识滴滴交易策略之二:司乘匹配

‍ 前文&#xff08;初识滴滴交易策略之一&#xff1a;交易市场)整体介绍了交易市场的定义、特点、技术特点和技术领域。在交易市场中&#xff0c;市场交易撮合——通常称之为“派单”——无疑是最重要的环节&#xff0c;以下将介绍滴滴交易市场中的司乘匹配技术。 对滴滴来说&…

全球523所高校,10425人共同学习,这所高校排第一!

Datawhale学习 总结&#xff1a;四月AIGC组队学习 在公众号回复“五月”可以提前进大模型应用交流群了&#xff0c;探索大模型的产品应用。回复“AIGC”&#xff0c;可以进AIGC交流群&#xff0c;用AIGC工具为自己打工。五月组队学习这周会在群内分享。 五月组队学习预告 全球…

2023年国内CDGA/CDGP数据治理认证考试报名入口

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

DNDC模型三:气象数据、土地数据、土壤数据、区域数据制备

查看原文>>>最新DNDC模型在土地利用变化、未来气候变化下的建模方法及温室气体时空动态模拟实践技术应用 由于全球变暖、大气中温室气体浓度逐年增加等问题的出现&#xff0c;“双碳”行动特别是碳中和已经在世界范围形成广泛影响。国家领导人在多次重要会议上讲到&a…

Python长时间序列遥感数据处理及在全球变化、物候提取、植被变绿与固碳分析、生物量估算与趋势分析

植被是陆地生态系统中最重要的组分之一&#xff0c;也是对气候变化最敏感的组分&#xff0c;其在全球变化过程中起着重要作用&#xff0c;能够指示自然环境中的大气、水、土壤等成分的变化&#xff0c;其年际和季节性变化可以作为地球气候变化的重要指标。此外&#xff0c;由于…