C语言-数据结构-队列

devtools/2025/1/16 23:19:17/

目录

1.队列的特点

2.队列的实现

2.1.初始化队列

2.2.入队列

2.2.1.入空队列

2.2.2.入非空队列

2.3.出队列

2.4.销毁队列

2.5.完整代码

3.实际应用


1.队列的特点

        队列是一种常见的数据结构,它遵循先进先出(FIFO, First In First Out)原则,即先加入队列的元素先被处理(出队),后加入的元素后处理,这一点和栈的特性完全相反队列广泛应用于计算机科学中,尤其是在任务调度、消息传递、数据缓存等场景中。

        那么关于队列的核心就是先进先出,后进后出。

2.队列的实现

        首先需要确定队列的数据结构如何设计?

        核心思路:使用单链表挂载数据节点,队列的队头指针和队尾指针指向链表头和链表

        由于队列不同于栈的特性,队列可以两端操作,因此需要两个指针来维护队头和队尾,那么最基本的队列的结构就可以设计出来了,如下:

/* 数据节点 */
typedef struct _DataNode {u32 data;struct _DataNode *next;
}DataNode;/* 队列 */
typedef struct _Queue {struct _DataNode *head;struct _DataNode *tail;u32 size;
}Queue;

        队列中还加入了队列大小size属性,这里如果做的更通用一些还可以考虑多线程场景,加入锁等,可根据实际需要自行调整。

2.1.初始化队列

        初始化队列就是初始化对象的过程,申请内存然后初始化队列的成员,最后返回队列即可,刚开始初始化队列队列为空,将队头队尾指针置空即可。

/* 初始化队列 */
Queue *init_queue() {Queue *q = NULL;q = (Queue *)malloc(sizeof(Queue));if (!q) {return NULL;}q->size = 0;q->head = NULL;q->tail = NULL;return q;
}

2.2.入队列

        入队列需要考虑的问题稍微复杂一些,首先要考虑的是空队列怎么办?非空队列怎么办?

        空队列和非空队列的头尾指针的指向是不一样的~~~

2.2.1.入空队列

        入空队列操作简单,创建数据节点,将队头队尾指针都指向该数据节点即可,因为此时只有一个数据节点。

2.2.2.入非空队列

        入非空队列的过程即队头指针的指向不变,队尾指针指向新的节点,也就是说原来队尾指针的next指向新节点,新队尾指针指向新的节点。

队列完整代码如下:

/* 入队列 */
u8 enqueue(Queue *q, u32 data) {DataNode *new = NULL;new = (DataNode *)malloc(sizeof(DataNode));if (!new) {return FALSE; }new->data = data;new->next = NULL;printf("info, enqueue addr:%p\n", new);/* 空队列 */if (q->size == 0) {    q->head = new;q->tail = new;}else {q->tail->next = new;q->tail = new;}q->size++;return TRUE;
}

2.3.出队列

        出队列的过程和入队列相反,只需要修改队头指针即可,然后返回原有的队头节点即可。

出队完整代码如下:

/* 出队列 */
DataNode *dequeue(Queue *q) {DataNode *node = NULL;if (q->size) {node = q->head;q->head = q->head->next;q->size--;}printf("info, dequeue addr:%p\n", node);return node;
}

2.4.销毁队列

        销毁队列的过程和出队列的过程类似,只需要从队头开始遍历,直到队列中没有元素为止。

/* 销毁队列 */
void destory_queue(Queue *que) {if (!que) {return;}while(que->size) {DataNode *node = que->head;printf("info, destory_queue addr:%p\n", node);que->head = que->head->next;free(node);node = NULL;que->size--;}free(que);que = NULL;
}

2.5.完整代码

#include <stdio.h>
#include <stdlib.h>typedef unsigned char u8;
typedef unsigned int u32;#define FALSE 0
#define TRUE 1/* 数据节点 */
typedef struct _DataNode {u32 data;struct _DataNode *next;
}DataNode;/* 队列 */
typedef struct _Queue {struct _DataNode *head;struct _DataNode *tail;u32 size;
}Queue;/* 初始化队列 */
Queue *init_queue() {Queue *q = NULL;q = (Queue *)malloc(sizeof(Queue));if (!q) {return NULL;}q->size = 0;q->head = NULL;q->tail = NULL;return q;
}/* 销毁队列 */
void destory_queue(Queue *que) {if (!que) {return;}while(que->size) {DataNode *node = que->head;printf("info, destory_queue addr:%p\n", node);que->head = que->head->next;free(node);node = NULL;que->size--;}free(que);que = NULL;
}/* 入队列 */
u8 enqueue(Queue *q, u32 data) {DataNode *new = NULL;new = (DataNode *)malloc(sizeof(DataNode));if (!new) {return FALSE; }new->data = data;new->next = NULL;printf("info, enqueue addr:%p\n", new);/* 空队列 */if (q->size == 0) {    q->head = new;q->tail = new;}else {q->tail->next = new;q->tail = new;}q->size++;return TRUE;
}/* 出队列 */
DataNode *dequeue(Queue *q) {DataNode *node = NULL;if (q->size) {node = q->head;q->head = q->head->next;q->size--;}printf("info, dequeue addr:%p\n", node);return node;
}int main() {Queue *que = NULL;que = init_queue();if (!que) {printf("init queue failed !\n");return -1;}if (!enqueue(que, 10)) {printf("enqueue failed !\n");return -1;}if (!enqueue(que, 100)) {printf("enqueue failed !\n");return -1;}DataNode *node = dequeue(que);printf("info, dequeue node value:%u\n", node->data);free(node);node = NULL;destory_queue(que);return 0;
}

运行结果:

3.实际应用

dpdk中关于ring的描述:

        dpdk中关于环形队列的设计非常巧妙,感兴趣的可以自行研究。


http://www.ppmy.cn/devtools/151095.html

相关文章

electron编写一个macOS风格的桌面应用

electron编写一个macOS风格的桌面应用 基于vue3vite&#xff0c;看一下最后的效果&#xff1a; 针对原始的electron模板&#xff0c;做了如下几点调整&#xff1a; 背景边框进行了圆角处理隐藏了原始的titleBar增加了macOS风格的窗口管理工具&#xff0c;就是交通灯按钮组实现…

api开发及运用小红书笔记详情api如何获取笔记详情信息

item_get_video-获得某书笔记详情 smallredbook.item_get_video 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,i…

RPC 源码解析~Apache Dubbo

解析 RPC&#xff08;远程过程调用&#xff09;的源码可以帮助你深入理解其工作原理和实现细节。为了更好地进行源码解析&#xff0c;我们选择一个流行的 RPC 框架——Apache Dubbo 作为示例。Dubbo 是一个高性能、轻量级的开源 Java RPC 框架&#xff0c;广泛应用于企业级应用…

机器学习在服务监控中的创新应用:提升运维效率与可靠性

《机器学习在服务监控中的创新应用:提升运维效率与可靠性》 一、引言 在当今复杂的信息技术环境中,服务监控对于确保系统的稳定运行至关重要。传统的服务监控方法往往依赖于预定义的阈值和规则,但在面对复杂多变的服务行为时,这些方法可能会显得力不从心。机器学习的出现…

AI知识-TF-IDF技术(Term Frequency-Inverse Document Frequency)

摘要 TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09;是一种常见的统计方法&#xff0c;用于评估一个词对于一个文档集或一个语料库中的其中一份文档的重要性。本文将全面阐述TF-IDF的通俗理解、技术原理、应用场景&#xff0c;并做以总结。 通俗理…

《OpenCV》——模版匹配

文章目录 OpenCV——模版匹配简介模版匹配使用场景OpenCV 中模板匹配的函数参数 OpenCV——模版匹配实例导入所需库读取图片并处理图片对模版图片进行处理进行模版匹配显示模版匹配的结果注意事项 OpenCV——模版匹配简介 OpenCV 是一个非常强大的计算机视觉库&#xff0c;其中…

Spring Boot 3.x 整合 Logback 日志框架(支持异步写入)

Spring Boot 3.x 整合 Logback 日志框架&#xff08;支持异步写入&#xff09; 在构建任何应用程序时&#xff0c;良好的日志管理都是必不可少的。日志可以帮助我们监控、调试和跟踪代码的运行情况。 1. 添加日志配置文件 在 /resources 资源目录下&#xff0c;创建名为 log…

Vue.js 组件的基本结构:模板、脚本和样式

Vue.js 组件的基本结构&#xff1a;模板、脚本和样式 大家好&#xff01;今天我们聊聊 Vue 组件的基本结构。如果你刚接触 Vue.js&#xff0c;可能会觉得 .vue 文件有点特殊。其实&#xff0c;Vue 组件是高度模块化的&#xff0c;分为三部分&#xff1a;模板、脚本 和 样式。接…