数据结构之队列的实现(附源码)
目录
一、队列的概念及结构
二、队列的实现
拓展:循环队列
三、初学的队列以及栈和队列结合的练习题
一、队列的概念及结构
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出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 进行接口测试时,对于简单的不需要处理的接口,直接请求即可,但是对于需要处理的接口,如需要转码、替换值等,则就麻烦一些,一般我们都是先手动把修改好的值拷贝到请求里再进行请…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...