当前位置: 首页 > news >正文

数据结构_队列(C语言实现)

一、队列的基本概念

1.队列定义

队列是一种先进先出的线性表数据结构(First in First out),现实中的例子就是,排队购票,先排队的先购票,购完票之后直接从这个队中离开,后来的在这个队后面排队,这就是队列。

如图;
在这里插入图片描述
这就是一个空的队列,从队尾入队,从队头出队

2.常见的基本操作

  • initQueue:初始化队列
  • empty: 判断队列是否为空
  • push:入队操作
  • pop:出队操作
  • Front:获取队头元素

3.数据结构定义

为了锻炼高度模块化(分层设计),这里我们直接嵌套,不在Queue中直接定义数组,而是重新抽象出一个独立的vector数据结构作为底层容器,让Queue通过组合的方式使用vector来实现其功能。这种设计强调关注点分离,将内存管理的职责交给vector模块,而Queue模块只需专注于队列特有的逻辑操作。

typedef struct Queue {vector* data;int size,head,tail;//size记录当前队列有多少元素
}Queue;

二、代码实现

首先引用头文件,宏定义队列的开始元素为多少,定义vector及Queue

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include <stdbool.h>
#define BEGIN_SIZE 6
typedef struct vector {int* val;int size;//记录当前容量
}vector;
typedef struct Queue {vector* data;int size,head,tail;//size记录当前队列有多少元素
}Queue;

初始化Queue

Queue *initQueue() {Queue* q = (Queue*)malloc(sizeof(Queue));q->data = initVector();q->head = q->tail = q->size = 0;return q;
}

要想初始化Queue,那么也就要初始化vector

vector* initVector()
{vector * v=(vector*)malloc(sizeof(vector));v->size = BEGIN_SIZE;v->val = (int*)malloc(sizeof(int) * BEGIN_SIZE);return v;
}

这样队列的初始化就实现了,下来我们依次实现队列的基本功能:

  • empty: 判断队列是否为空
  • push:入队操作
  • pop:出队操作
  • Front:获取队头元素

empty():

bool empty(Queue* q) {return q->size == 0;//如果当前元素的个数等于 0 ,那么则证明队列为空
}

push():

int push(Queue* q, int val) {checkFull(q); /*如果队列已经满了,扩容队列*/q->data->val[q->tail++] = val;q->size++;return 1;
}

pop():

int pop(Queue* q) {if (empty(q))/*如果队列为空的话,则返回-1代表弹出失败*/ {printf("pop: 队列为空\n");return -1;}int count = 0;while (count < q->tail - 1) {q->data->val[count] = q->data->val[count + 1];count++;}q->tail--;q->size--;return 1;
}

解释下,这里为什么count<q->tail-1 为什么不是 count<q->tail
例如,队列中有三个元素,那么tail的值就是3,count从0开始,一共要循环到3次,最后一次的count等于 2 ,这个时候 q->data->val[count] = q->data->val[count + 1];这一句就会变为q->data->val[2] = q->data->val[3];,此时 3 这个位置是tail的位置,在内存中并没有赋值,内存中的值是未定义的(可能是垃圾值)

Front():

int Front(Queue* q) {if (empty(q)) {printf("Front 队列为空\n");return -1;}return q->data->val[q->head];
}

反过头处理checkFull(),检查队列是否为满,满的话则需要扩容

checkFull():

void checkFull(Queue *q) {if (q->size == q->data->size) {int newSize = q->data->size * 2;int * newVal=(int *)realloc(q->data->val, sizeof(int) * newSize);if (newVal == NULL) {printf("error checkFull\n");exit(-1);}q->data->val = newVal;q->data->size = newSize;}return;
}

查看队列所有元素

outAll():

void outAll(Queue* q) {printf("Queue: ");for (int i = q->head; i < q->tail; i++) {printf("%3d ", q->data->val[i]);}printf("\n");return;
}

最后释放内存

freeQueue():

void freeQueue(Queue* q) {freeVector(q->data);free(q);return;
}

freeVector():

void freeVector(vector* v) {free(v->val);free(v);return;
}

main函数(测试函数)

int main() {Queue* q = initQueue();//初始化一个队列pop(q);//在空队列时弹出,应该输出 pop: 队列为空Front(q);//在空队列时获取队头元素,应该输出 Front: 队列为空srand(time(NULL));
#define MAX_OP 10for (int i = 0; i < MAX_OP; i++) {int op = rand() % 5, val = rand() % 100;switch (op) {case 0://pop操作printf("front of queue %d 弹出此元素\n", Front(q));pop(q);break;case 1:case 2:case 3:case 4://push操作printf("将 %d push进队列\n", val);push(q, val);break;}outAll(q);}printf("队头元素为: %3d\n",Front(q));return 0;
}

完整代码

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define BEGIN_SIZE 6
typedef struct vector {int* val;int size;//记录当前容量
}vector;
typedef struct Queue {vector* data;int size, head, tail;//size记录当前队列有多少元素
}Queue;
vector* initVector()
{vector * v=(vector*)malloc(sizeof(vector));if (v == NULL) {printf("error initVector\n");exit(-1);}v->size = BEGIN_SIZE;v->val = (int*)malloc(sizeof(int) * BEGIN_SIZE);return v;
}
Queue *initQueue() {Queue *q = (Queue*)malloc(sizeof(Queue));if (q == NULL) {printf("error initQueue\n");exit(-1);}q->data = initVector();q->head = q->tail = q->size = 0;return q;
}
bool empty(Queue* q) {return q->size == 0;
}
void checkFull(Queue *q) {if (q->size == q->data->size) {int newSize = q->data->size * 2;int * newVal=(int *)realloc(q->data->val, sizeof(int) * newSize);if (newVal == NULL) {printf("error checkFull\n");exit(-1);}q->data->val = newVal;q->data->size = newSize;}return;
}
int push(Queue* q, int val) {checkFull(q); /*如果队列已经满了,扩容队列*/q->data->val[q->tail++] = val;q->size++;return 1;
}int pop(Queue* q) {if (empty(q))/*如果队列为空的话,则返回-1代表弹出失败*/ {printf("pop: 队列为空\n");return -1;}int count = 0;while (count < q->tail - 1) {q->data->val[count] = q->data->val[count + 1];count++;}q->tail--;q->size--;return 1;
}int Front(Queue* q) {if (empty(q)) {printf("Front: 队列为空\n");return -1;}return q->data->val[q->head];
}void outAll(Queue* q) {printf("Queue: ");if (empty(q)) {printf("NULL\n");return;}for (int i = q->head; i < q->tail; i++) {printf("%3d ", q->data->val[i]);}printf("\n");return;
}void freeVector(vector* v) {free(v->val);free(v);return;
}void freeQueue(Queue* q) {freeVector(q->data);free(q);return;
}int main() {Queue* q = initQueue();//初始化一个队列pop(q);//在空队列时弹出,应该输出 pop: 队列为空Front(q);//在空队列时获取队头元素,应该输出 Front: 队列为空srand(time(NULL));
#define MAX_OP 10for (int i = 0; i < MAX_OP; i++) {int op = rand() % 5, val = rand() % 100;switch (op) {case 0://pop操作printf("front of queue %d 弹出此元素\n", Front(q));pop(q);break;case 1:case 2:case 3:case 4://push操作printf("将 %d push进队列\n", val);push(q, val);break;}outAll(q);}printf("队头元素为: %3d\n",Front(q));return 0;
}
http://www.dtcms.com/a/363464.html

相关文章:

  • 图论简介与图神经网络(Dijkstra算法,图卷积网络GCN实战)
  • 只需几条命令,本地体验微软最新长文本语音合成 VibeVoice(支持中文)
  • 电子电气架构 --- 当前企业EEA现状(上)
  • 2025牛客暑期多校训练营4(FBDGI)
  • MacOS - 记录MacOS发烫的好几天 - 幕后黑手竟然是
  • KVM 虚拟化基础与实操
  • 新质生产力的中枢神经:人工智能+时代的实时视频架构
  • Ubuntu 用户和用户组
  • rocketmq console dashboard 2.0控制台
  • 均匀分布直线阵的常规波束形成方位谱和波束图
  • MySQL中binlog、redolog与undolog的不同之处解析
  • 存算一体前沿技术——无需比较器即可高效排序,性能提升高达百倍
  • 轻型载货汽车变速器设计cad+设计说明书
  • 广东某地非金属矿山自动化监测服务项目
  • “转”若惊鸿,电磁“通”——耐达讯自动化RS485转Profinet点亮能源新章
  • Understanding the Flap T in American English
  • 视频转文字软件哪个免费好用?2025年5款实用工具实测,助力办公效率!
  • 无人机GPS悬停模块技术解析
  • # pdf.js完全指南:构建现代Web PDF查看与解析解决方案
  • 无人机各种接头焊接方法
  • AI 時代的白帽與黑帽 SEO:最佳實踐與趨勢解析
  • RAG实战 || 代码实现流程 || 简洁明了
  • java日志框架简述1
  • 【版权音乐主题系列讲座·同济大学站】顺利结束啦!
  • Java试题-选择题(30)
  • 【IntelliJ IDEA】插件分享
  • RL【1】:Basic Concepts
  • 一个真正跨平台可用的免费PDF解决方案
  • PyTorch 训练随机卡死复盘:DataLoader × OpenCV 多进程死锁,三步定位与彻底修复
  • 金融学硕士这么多,都说只有中国人民大学与加拿大女王大学金融硕士值得读