数据结构之队列的实现(附源码)
目录
一、队列的概念及结构
二、队列的实现
拓展:循环队列
三、初学的队列以及栈和队列结合的练习题
一、队列的概念及结构
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头

二、队列的实现
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。

具体代码如下(C语言实现):
#pragma once//Queue.h
// 链式结构:表示队列#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int QDateType;typedef struct QListNode
{struct QListNode* _next;QDateType _data;
}QNode;// 队列的结构
typedef struct Queue
{QNode* _front;//队头QNode* _rear;//队尾int size;
}Queue;// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QDateType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QDateType QueueFront(Queue* q);
// 获取队列队尾元素
QDateType QueueBack(Queue* q);
// 获取队列中有效元素个数
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);
//Queue.c
#include "Queue.h"void QueueInit(Queue* q)
{assert(q);q->_front = NULL;q->_rear = NULL;q->size = 0;
}void QueuePush(Queue* q, QDateType data)
{assert(q);QNode* tmp = (QNode*)malloc(sizeof(QNode));if (tmp == NULL){perror("tmp malloc");exit(-1);}tmp->_data = data;tmp->_next = NULL;if (q->_rear == NULL){q->_front = q->_rear = tmp;}else{q->_rear->_next = tmp;q->_rear = tmp;}q->size++;
}void QueuePop(Queue* q)
{assert(q);assert(QueueEmpty(q));if (q->_front->_next == NULL){free(q->_front);q->_front = q->_rear = NULL;}else{QNode* next = q->_front->_next;free(q->_front);q->_front = next;}q->size--;
}QDateType QueueFront(Queue* q)
{assert(q);assert(QueueEmpty(q));return q->_front->_data;
}QDateType QueueBack(Queue* q)
{assert(q);assert(QueueEmpty(q));return q->_rear->_data;
}int QueueSize(Queue* q)
{assert(q);return q->size;
}int QueueEmpty(Queue* q)
{assert(q);return q->size;
}void QueueDestroy(Queue* q)
{assert(q);QNode* cur = q->_front;while (cur){Queue* next = cur->_next;free(cur);cur = next;}q->_front = q->_rear = NULL;q->size = 0;
}
//test.c
#include "Queue.h"void test02()
{Queue q1;QueueInit(&q1);QueuePush(&q1, 1);QueuePush(&q1, 2);QueuePush(&q1, 3);QueuePush(&q1, 4);QueuePush(&q1, 5);QueuePop(&q1);while (QueueEmpty(&q1)){printf("%d ", QueueFront(&q1));QueuePop(&q1);}printf("\n");QueueDestroy(&q1);
}int main()
{test02();return 0;
}
拓展:循环队列

如上图所示:循环队列的节点数一般会比要求的节点数多一个,以便区分空的循环队列和满的循环队列。空的循环队列front和rear指向同一个节点,满的循环队列可以理解为rear = front + 1。
三、初学的队列以及栈和队列结合的练习题
题目一:设计循环队列
MyCircularQueue(k): 构造器,设置队列长度为 k 。Front: 从队首获取元素。如果队列为空,返回 -1 。Rear: 获取队尾元素。如果队列为空,返回 -1 。enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。isEmpty(): 检查循环队列是否为空。isFull(): 检查循环队列是否已满。
typedef struct
{int* a;int front;int rear;int k;
} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k)
{MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));obj->a = (int*)malloc(sizeof(int)*(k+1));obj->front = obj->rear = 0;obj->k = k;return obj;
}bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{//front和rear相等即为空return obj->front == obj->rear;
}bool myCircularQueueIsFull(MyCircularQueue* obj)
{//数学方法判满return (obj->rear + 1) % (obj->k + 1) == obj->front;
}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{if(myCircularQueueIsFull(obj))return false;obj->a[obj->rear] = value;++obj->rear;//不然rear可能越界obj->rear %= (obj->k+1);return true;
}bool myCircularQueueDeQueue(MyCircularQueue* obj)
{if(myCircularQueueIsEmpty(obj))return false;obj->front++;obj->front %= (obj->k+1);return true;
}int myCircularQueueFront(MyCircularQueue* obj)
{if(myCircularQueueIsEmpty(obj))return -1;elsereturn obj->a[obj->front];
}int myCircularQueueRear(MyCircularQueue* obj)
{if(myCircularQueueIsEmpty(obj))return -1;else//数学方法return obj->a[(obj->rear + obj->k) % (obj->k + 1)];
}void myCircularQueueFree(MyCircularQueue* obj)
{free(obj->a);free(obj);
}
题目二:用队列实现栈
思路:用两个队列,保持一个队列为空一个不为空,当要出栈的时候就将不为空的队列中除了队尾的元素全都入到为空的队列中,然后将唯一的那个元素出栈。
typedef int QDateType;typedef struct QListNode
{struct QListNode* _next;QDateType _data;
}QNode;// 队列的结构
typedef struct Queue
{QNode* _front;QNode* _rear;int size;
}Queue;void QueueInit(Queue* q)
{assert(q);q->_front = NULL;q->_rear = NULL;q->size = 0;
}void QueuePush(Queue* q, QDateType data)
{assert(q);QNode* tmp = (QNode*)malloc(sizeof(QNode));if (tmp == NULL){perror("tmp malloc");exit(-1);}tmp->_data = data;tmp->_next = NULL;if (q->_rear == NULL){q->_front = q->_rear = tmp;}else{q->_rear->_next = tmp;q->_rear = tmp;}q->size++;
}void QueuePop(Queue* q)
{assert(q);assert(QueueEmpty(q));if (q->_front->_next == NULL){free(q->_front);q->_front = q->_rear = NULL;}else{QNode* next = q->_front->_next;free(q->_front);q->_front = next;}q->size--;
}QDateType QueueFront(Queue* q)
{assert(q);assert(QueueEmpty(q));return q->_front->_data;
}QDateType QueueBack(Queue* q)
{assert(q);assert(QueueEmpty(q));return q->_rear->_data;
}int QueueSize(Queue* q)
{assert(q);return q->size;
}int QueueEmpty(Queue* q)
{assert(q);return q->size;
}void QueueDestroy(Queue* q)
{assert(q);QNode* cur = q->_front;while (cur){Queue* next = cur->_next;free(cur);cur = next;}q->_front = q->_rear = NULL;q->size = 0;
}typedef struct
{Queue q1;Queue q2;
} MyStack;MyStack* myStackCreate()
{MyStack* tmp = (MyStack*)malloc(sizeof(MyStack));QueueInit(&tmp->q1);QueueInit(&tmp->q2);return tmp;
}void myStackPush(MyStack* obj, int x)
{if(QueueEmpty(&obj->q1)){QueuePush(&obj->q1, x);}else{QueuePush(&obj->q2, x);}
}int myStackPop(MyStack* obj)
{Queue* empty = &obj->q1;Queue* noempty = &obj->q2;if(QueueEmpty(&obj->q1)){empty = &obj->q2;noempty = &obj->q1;}while(QueueSize(noempty) > 1){QueuePush(empty, QueueFront(noempty));QueuePop(noempty);}int top = QueueFront(noempty);QueuePop(noempty);return top;
}int myStackTop(MyStack* obj)
{if(QueueEmpty(&obj->q1))return QueueBack(&obj->q1);elsereturn QueueBack(&obj->q2);
}bool myStackEmpty(MyStack* obj)
{int ret1, ret2;if(QueueEmpty(&obj->q1) == 0)ret1 = 0;elseret1 = 1;if(QueueEmpty(&obj->q2) == 0)ret2 = 0;elseret2 = 1;if(ret1 == 0 && ret2 == 0)return true;elsereturn false;
}void myStackFree(MyStack* obj)
{QueueDestroy(&obj->q1);QueueDestroy(&obj->q2);free(obj);
}
题目三:用栈实现队列
思路:使用两个栈,一个push栈一个pop栈,先往push栈中堆入元素,出队时,先将push栈中的元素先pop到pop栈中,再从pop栈中pop元素,其间再有元素堆入入到push栈中。
typedef int STDataType;
typedef struct Stack
{STDataType* _a;int _top; // 栈顶int _capacity; // 容量
}Stack;void StackInit(Stack* ps)
{assert(ps);ps->_a = NULL;ps->_top = 0;ps->_capacity = 0;
}void StackPush(Stack* ps, STDataType data)
{assert(ps);if (ps->_capacity == ps->_top){int newCapacity = ps->_capacity == 0 ? 4 : ps->_capacity * 2;STDataType* tmp = (STDataType*)realloc(ps->_a,sizeof(STDataType) * newCapacity);if (tmp == NULL){perror("realloc fail");exit(-1);}ps->_a = tmp;ps->_capacity = newCapacity;}ps->_a[ps->_top] = data;ps->_top++;
}void StackPop(Stack* ps)
{assert(ps);assert(ps->_top > 0);ps->_top--;
}STDataType StackTop(Stack* ps)
{assert(ps);assert(ps->_top > 0);return ps->_a[ps->_top - 1];
}int StackSize(Stack* ps)
{assert(ps);return ps->_top;
}int StackEmpty(Stack* ps)
{return ps->_top;
}void StackDestroy(Stack* ps)
{assert(ps);free(ps->_a);ps->_a = NULL;ps->_capacity = 0;ps->_top = 0;
}typedef struct
{Stack pushst;Stack popst;
} MyQueue;MyQueue* myQueueCreate()
{MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));StackInit(&obj->pushst);StackInit(&obj->popst);return obj;
}void myQueuePush(MyQueue* obj, int x)
{StackPush(&obj->pushst, x);
}int myQueuePeek(MyQueue* obj)
{//pop栈为空就往其中堆入元素if(StackEmpty(&obj->popst) == 0){while(StackEmpty(&obj->pushst) > 0){StackPush(&obj->popst, StackTop(&obj->pushst));StackPop(&obj->pushst);}}return StackTop(&obj->popst);
}int myQueuePop(MyQueue* obj)
{int front = myQueuePeek(obj);StackPop(&obj->popst);return front;
}bool myQueueEmpty(MyQueue* obj)
{int ret1, ret2;if(StackEmpty(&obj->pushst) == 0)ret1 = 0;elseret1 = 1;if(StackEmpty(&obj->popst) == 0)ret2 = 0;elseret2 = 1;if(ret1 == 0 && ret2 == 0)return true;elsereturn false;
}void myQueueFree(MyQueue* obj)
{StackDestroy(&obj->pushst);StackDestroy(&obj->popst);free(obj);
}
相关文章:
数据结构之队列的实现(附源码)
目录 一、队列的概念及结构 二、队列的实现 拓展:循环队列 三、初学的队列以及栈和队列结合的练习题 一、队列的概念及结构 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(Fi…...
[A题]2023 年全国大学生数学建模比赛思路、代码更新中.....
💥1 概述 构建以新能源为主体的新型电力系统,是我国实现“碳达峰”“碳中和”目标的一项重要措施。塔式太阳能光热发电是一种低碳环保的新型清洁能源技术[1]。定日镜是塔式太阳能光热发电站(以下简称塔式电站)收集太阳能的基本组…...
Tailwind 练手项目
Tailwind 练手项目 用到的技巧 Tailwind CSS 速成 应该都提过了,我不记得这里有什么特别新的知识 整体完成图大概这样: 一个纯静态页面,没有做 JS 之类的特效,不过做了移动端适配,说实话我写到一半的时候改了不少………...
SpringMVC_SSM整合
一、回顾SpringMVC访问接口流程 1.容器加载分析 容器分析 手动注册WebApplicationContext public class ServletConfig extends AbstractDispatcherServletInitializer {Overrideprotected WebApplicationContext createServletApplicationContext() {//获取SpringMVC容器An…...
【操作系统】电脑上没有IIS怎么办
文章目录 前言一、查看二、解决 前言 有的新机刚开始在计算机-管理-服务下没有IIS网络服务怎么办。 一、查看 桌面计算机/此电脑 鼠标右键:管理 服务和应用 发现没有IIS 二、解决 控制面板 程序和功能 启动或关闭Windows功能 IIS相关的所有功能选中ÿ…...
【vue】vue项目中批量下载文件并打压缩包
前言 一开始用的是循环单个文件下载,即从后台获取到文件url列表,循环对每个url单独进行下载,这样的问题是每调用一次下载,浏览器都会进行“另存为”的弹框,很麻烦!!! 关闭“下载前…...
Linux中的软件管家——yum
目录 编辑 一,软件安装的方式 二,对yum的介绍 1.yum的作用 2,yum的库 三,yum下载软件的操作 1.yumlist 2.yuminstall 3.yumremove 四,yum源的转换 一,软件安装的方式 软件安装的方式大概分为三种…...
安卓绘制原理概览
绘制原理 Android 程序员都知道 Android 的绘制流程分为 Measure、Layout、Draw 三步骤,其中 Measure 负责测量 View 的大小Layout 负责确定 View 的位置Draw 负责将 View 画在屏幕上 由 ViewRootImpl 实现的 performTraversal 方法是 Measure、layout、draw 的真正…...
接口测试工具开发文档
1 开发规划 1.1 开发人员 角 色 主要职责 负责模块 人员 备注 n xxx模块 xxx 1.2 开发计划 <附开发计划表> 1.3 开发环境和工具 开发工具 工具 作用 Notepad 编辑器 Perl 解释器 2 总体设计 设计思路:因为测试app和server。首先必须…...
面试题速记:JavaScript有哪些数据类型,它们的区别是?
JavaScript有哪些数据类型,它们的区别? JavaScript共有八种数据类型,分别是 Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。 其中 Symbol 和 BigInt 是ES6 中新增的数据类型: ●Symbol 代表创建后独一无二…...
Spring Cloud面试题
为什么需要学习Spring Cloud 不论是商业应用还是用户应用,在业务初期都很简单,我们通常会把它实现为单体结构的应用。但是,随着业务逐渐发展,产品思想会变得越来越复杂,单体结构的应用也会越来越复杂。这就会给应用带…...
计算机网络自顶向下-web页面请求历程
1. 准备: DHCP、 UDP、 IP 和以太网 假定 Bob 启动他的便携机,然后将其用一根以太网电缆连接到学校的以太网交换机 , 交换机与学校的路由器相连。学校的路由器与一个 ISP 连接, 本例中 ISP 为 comcast.net ,为学校提供了 DNS 服务…...
打造西南交通感知新范式,闪马智能携手首讯科技落地创新中心
9月4日,2023年中国国际智能产业博览会(以下简称“智博会”)在重庆拉开帷幕。大会期间,由上海闪马智能科技有限公司(以下简称“闪马智能”)与重庆首讯科技股份有限公司(以下简称“首讯科技”&…...
Android11去掉Settings中的网络和互联网一级菜单
碰到一个不要wifi不要蓝牙的项目,客户要求去掉Settings中的网络和互联网一级菜单,因为硬件都不贴,所以软件对应也要去掉。 我们可以根据packages/apps/Settings/res/xml/top_level_settings.xml的布局文件找到TopLevelNetworkEntryPreferenc…...
基于Python开发的五子棋小游戏(源码+可执行程序exe文件+程序配置说明书+程序使用说明书)
一、项目简介 本项目是一套基于Python开发的五子棋小游戏,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Python学习者。 包含:项目源码、项目文档、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试&a…...
JDBC入门到精通-10w总结
JDBC核心技术 笔记是以尚硅谷讲师宋红康JDBC课程为基础,加入自身学习体会,略有修改 第1章:JDBC概述 JDBC是java应用程序和数据库之间的桥梁。JDBC提供一组规范(接口)。向上是面向应用API,共应用程序使用。向…...
Linux之查看so/bin依赖(三十一)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...
day-45 代码随想录算法训练营(19)动态规划 part 07
70.爬楼梯(进阶) 分析:基本动态规划转换为完全背包,因为1、2 两种上楼梯方式是无限选择的 思路: 1. j 表示 容量为 j 时,装满有dp[j]种方法2. dp[j]dp[j-nums[i]]3. 初始化 dp[0]1,dp[1]14. 遍历顺序&am…...
static关键字和final关键字
在java的关键字中,static关键字和final关键字是两个必须掌握的关键字。static关键字和final关键字用法多样,且在一定环境下使用,可以提高程序的运行性能,优化程序的结构。下面将依次介绍static关键字和final关键字。注意ÿ…...
使用Postman如何在接口测试前将请求的参数进行自定义处理
1、前言 当我们使用 Postman 进行接口测试时,对于简单的不需要处理的接口,直接请求即可,但是对于需要处理的接口,如需要转码、替换值等,则就麻烦一些,一般我们都是先手动把修改好的值拷贝到请求里再进行请…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
