C语言队列实现参考示例

news2024/9/29 21:28:33

C语言队列实现参考示例

目录

  • C语言队列实现参考示例
    • 前言
    • 1 代码实现
      • 1.1 实现方案
      • 1.2 代码编写
    • 结束语

前言

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

队列在应用开发中经常会使用到,常见的队列有链式队列和循环队列,具体的原理我这里就不详细解析了,感兴趣的同学可以自行查阅资料。

1 代码实现

1.1 实现方案

我这里主要使用C语言实现一个通用的循环队列,示意图如下:
请添加图片描述
先划分一块缓存用来存放队列的数据,然后通过头指针和尾指针,分别指向队列的第一个元素和最后一个元素,当数据入队时,尾指针后移,当数据出队时,头指针后移,从而实现一个闭环。
注:队列中的元素并不是某个特定类型的变量,它可以是整形,可以是数组,也可以是结构体,也就是说这是一个通用的框架。

1.2 代码编写

队列实现定义(h文件):

#ifndef __QUEUE_H_
#define __QUEUE_H_

/*********************************************************************
 * @brief       队列类型定义
 *********************************************************************/
typedef struct
{
    volatile unsigned int   front;           // front为起始元素
    volatile unsigned int   rear;            // rear为最后一个元素
    volatile unsigned int   count;           // 元素个数
    unsigned int            element_size;    // 每个元素的字节数(这里的元素可以是任意类型的变量)
    unsigned int            element_num;     // 队列深度(元素最大个数,以元素的类型为基本单位,例如元素是结构体,那element_num就是这个结构体的数量)
    void                    *buf;            // 缓存区(大小为element_size * element_num)
}queue_type;

/*********************************************************************
 * @brief       队列初始化
 * @param[in]   queue: 队列指针
 * @param[in]   buf: 队列中缓存
 * @param[in]   element_size:队列每个元素的字节数
 * @param[in]   element_num: 队列深度(元素最大个数)
 * @return      None
 *********************************************************************/
void queue_create(queue_type *queue, void *buf, unsigned int element_size, unsigned int element_num);

/*********************************************************************
 * @brief       判断队列是否为空
 * @param[in]   queue: 队列指针
 * @return      1-TRUE or 0-FALSE
 *********************************************************************/
unsigned char queue_is_empty(queue_type *queue);

/*********************************************************************
 * @brief       判断队列是否已满
 * @param[in]   queue: 队列指针
 * @return      TRUE or FALSE
 *********************************************************************/
unsigned char queue_is_full(queue_type *queue);

/*********************************************************************
 * @brief       向队列添加一个元素
 * @param[in]   queue: 队列指针
 * @param[in]   value: 要添加的元素

*********************************************************************/
unsigned char queue_append_byte(queue_type *queue, void *value);
  
/*********************************************************************
 * @brief       向队列添加多个元素
 * @param[in]   queue: 队列指针
 * @param[in]   values: 要添加的元素指针
 * @param[in]   element_num: 要添加元素个数
 * @return      实际添加的元素个数
 *********************************************************************/
unsigned int queue_append_nbyte(queue_type *queue, void *values, unsigned int element_num);
  
/*********************************************************************
 * @brief       从队列读取一个元素
 * @param[in]   queue: 队列指针
 * @param[in]   value: 存放要读取的元素指针
 * @return      1-TRUE or 0-FALSE
 *********************************************************************/
unsigned char queue_delete_byte(queue_type *queue, void *value);
  
/*********************************************************************
 * @brief       从队列读取多个元素
 * @param[in]   queue: 队列指针
 * @param[out]  values: 存放要读取的元素指针
 * @param[in]   element_num: 要读取的元素个数
 * @return      实际读取的元素个数
 *********************************************************************/
unsigned int queue_delete_nbyte(queue_type *queue, void *values, unsigned int element_num);
  
/*********************************************************************
 * @brief       清空队列
 * @param[in]   queue: 队列指针
 * @return      None
 *********************************************************************/
void queue_clear(queue_type *queue);
  
#endif

队列实现代码(c文件):

#include <string.h>
#include "queue.h"
#include <stdio.h>

/*********************************************************************
 * @brief       创建队列
 * @param[in]   queue: 队列指针
 * @param[in]   buf: 队列缓存(大小为element_size * element_num)
 * @param[in]   element_size: 队列每个元素的大小(这里的元素可以是任意类型的变量)
 * @param[in]   element_num: 队列最大元素个数(以元素的类型为基本单位,例如元素是一个结构体,那么element_num就是这个结构体的数量)
 * @return      None
 *********************************************************************/
void queue_create(queue_type *queue, void *buf, unsigned int element_size, unsigned int element_num)
{
    queue->buf = buf;
    queue->element_size = element_size;
    queue->element_num = element_num;
    queue->front = 0;
    queue->rear = 0;
    queue->count = 0;
}

/*********************************************************************
 * @brief       判断队列是否为空
 * @param[in]   queue: 队列指针
 * @return      1-TRUE or 0-FALSE
 *********************************************************************/
unsigned char queue_is_empty(queue_type *queue)
{
    return (queue->count == 0);
}

/*********************************************************************
 * @brief       判断队列是否已满
 * @param[in]   queue: 队列指针
 * @return      TRUE or FALSE
 *********************************************************************/
unsigned char queue_is_full(queue_type *queue)
{
    return (queue->count == queue->element_num);
}
  
/*********************************************************************
 * @brief       向队列添加一个元素
 * @param[in]   queue: 队列指针
 * @param[in]   value: 要添加的元素
 * @return      1-TRUE or 0-FALSE
 *********************************************************************/
unsigned char queue_append_byte(queue_type *queue, void *value)
{
    unsigned char *p;
  
    if (queue_is_full(queue))
    {
        return 0;
    }
  
    p = (unsigned char *)queue->buf;
    memcpy(p + queue->rear, (unsigned char *)value, queue->element_size);
     
    queue->rear += queue->element_size;
    if (queue->rear >= queue->element_size * queue->element_num)
    {
        queue->rear = 0;
    }
    queue->count ++;
    return 1;
}

/*********************************************************************
 * @brief       向队列添加多个元素
 * @param[in]   queue: 队列指针
 * @param[in]   values: 要添加的元素指针
 * @param[in]   element_num: 要添加的元素个数
 * @return      实际添加的元素个数
 *********************************************************************/
unsigned int queue_append_nbyte(queue_type *queue, void *values, unsigned int element_num)
{
    unsigned char *p;
    unsigned int cnt = 0;
  
    p = (unsigned char *)values;
    while(element_num --)
    {
        if (queue_append_byte(queue, p))
        {
            p += queue->element_size;
            cnt++;
        }
        else
        {
            break;
        }
    }
    return cnt;
}

/*********************************************************************
 * @brief       从队列读取一个元素
 * @param[in]   queue: 队列指针
 * @param[in]   value: 存放要读取的元素指针
 * @return      1-TRUE or 0-FALSE
 *********************************************************************/
unsigned char queue_delete_byte(queue_type *queue, void *value)
{
    unsigned char *p;
    if (queue_is_empty(queue))
    {
        return 0;
    }
  
    p = (unsigned char *)queue->buf;
    memcpy(value, p + queue->front, queue->element_size);
  
    queue->front += queue->element_size;
    if (queue->front >= queue->element_size * queue->element_num)
    {
        queue->front = 0;
    }
    queue->count --;
    return 1;
}

/*********************************************************************
 * @brief       从队列读取多个元素
 * @param[in]   queue: 队列指针
 * @param[out]  values: 存放要读取的元素指针
 * @param[in]   element_num: 要读取的元素长度
 * @return      实际读取的元素个数
 *********************************************************************/
unsigned int queue_delete_nbyte(queue_type *queue, void *values, unsigned int element_num)
{
    unsigned int cnt = 0;
    unsigned char *p;
  
    p = values;
    while(element_num--)
    {
        if (queue_delete_byte(queue, p))
        {
            p += queue->element_size;
            cnt++;
        }
        else
        {
            break;
        }
    }
    return cnt;
}

/*********************************************************************
 * @brief       清空队列
 * @param[in]   queue: 队列指针
 * @return      None
 *********************************************************************/
void queue_clear(queue_type *queue)
{
    queue->count = 0;
    queue->front = 0;
    queue->rear = 0;
}

使用示例:

/* 元素为char类型 */
queue_type queue;                         // 新建队列
char queue_buf[50];                       // 队列缓存区,存放50个元素
char test_data1 = 1;                      // 测试入队字符
char test_data2;                          // 测试出队字符
queue_create(&queue, queue_buf, 1, 50);   // 创建1个队列,每个元素大小为1byte,队列长度为50byte
queue_append_byte(&queue, &test_data1);   // 入队1个字符
queue_delete_byte(&queue, &test_data2);   // 出队1个字符

/* 元素为数组类型 */
queue_type queue;                         // 新建队列
uint8_t queue_buf[5*10];                  // 队列缓存区,存放10个元素,每个元素为5byte的数组
uint8_t test_buf1[5] = {1, 2, 3, 4, 5};   // 测试入队数组
uint8_t test_buf2[5];                     // 测试出队数组
queue_create(&queue, queue_buf, 5, 10);   // 创建1个队列,每个元素大小为5byte,队列长度为10
queue_append_byte(&queue, &test_buf1);    // 入队1个数组
queue_delete_byte(&queue, &test_buf2);    // 出队1个数组

/* 元素为结构体类型 */
queue_type queue;                         // 新建队列
typedef struct
{// 测试结构体类型
	uint8_t addr;
    uint8_t data;
} test_param_t; 
test_param_t queue_buf[10];                                // 队列缓存区,存放10个元素,每个元素为结构体queue_buf的大小
test_param_t test_buf1 = {1, 2};                           // 测试入队结构体
test_param_t test_buf2;                                    // 测试出队结构体
queue_create(&queue, queue_buf, sizeof(test_param_t), 10); // 创建1个队列,元素为queue_buf大小(2byte),队列长度为10
queue_append_byte(&queue, &test_buf1);                     // 入队1个结构体
queue_delete_byte(&queue, &test_buf2);                     // 出队1个结构体

结束语

我这里用循环队列做了一个通用框架,这种方式的好处是同一套代码可以用在各种自定义变量上面,只需要在初始化的时候,设置好这个队列的元素类型和长度即可。当然,我这里只是列举了一种方式,实际上还有很多方法实现。
好了,关于使用C语言实现队列的方法就介绍到这里,如果你们有什么问题,欢迎评论区留言。

如果这篇文章能够帮到你,就…懂的。
请添加图片描述

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

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

相关文章

Java 多线程练习

目录 1.定时器操作&#xff08;实现电脑定时关机&#xff09;。 2. 每个月的月末(02:00:00) 执行一次代码 3. 模拟售票 4. 用15个线程实现&#xff0c;求123456789 之间放-和为100的表达式&#xff08;11个结果&#xff09;&#xff0c;如果一个线程求出结果&#xff0c; 立…

【LeetCode】383. 赎金信

题目&#xff1a;383. 赎金信 由于此题只含有小写字母,并且magazine里面的字母不可重复使用. 故首先用一个长度为26的整形数组记录magazine里字母出现的次数。 再用这个整形数组跟ransomeNote进行遍历比较&#xff0c;当数组中出现-1时&#xff0c;说明false,否则true. 代码&am…

大数据Flink(五十二):Flink中的批和流以及性能比较

文章目录 Flink中的批和流以及性能比较 ​​​​​​​​​​​​​​一、Flink中的批和流

python与深度学习(九):CNN和cifar10

目录 1. 说明2. cifar10实战2.1 导入相关库2.2 加载数据2.3 数据预处理2.4 数据处理2.5 构建网络模型2.6 模型编译2.7 模型训练2.8 模型保存2.9 模型评价2.10 模型测试2.11 模型训练结果的可视化 3. cifar10的CNN模型可视化结果图4. 完整代码5. 改进后的代码和结果 1. 说明 本…

史上最强,Python自动化测试框架整理,搭建框架看这篇就够了...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 什么是测试框架呢…

明星代言注意事项:确保代言活动成功的关键要素

对于商家而言&#xff0c;聘请明星代言自己的品牌产品&#xff0c;无非就是为了利用明星的人气为品牌加持热度&#xff0c;吸引明星粉丝和消费者的关注&#xff0c;增加产品转化&#xff0c;塑造品牌形象。明星代言是一项重要的市场营销策略&#xff0c;但同时也需要注意一些关…

美化与保护合二为一:3个功能厉害的水印app

每个人都有自己珍视的照片回忆&#xff0c;但在互联网上共享这些照片时&#xff0c;担心他人未经允许使用它们是很常见的。幸运的是&#xff0c;现在有了加水印软件&#xff0c;我们可以以有效的方式保护我们的珍贵照片。通过在图片上添加个性化的水印&#xff0c;你可以在不影…

textarea文本高亮选中

最近在实现原文/译文句段高亮对比显示&#xff0c;和有道翻译类似&#xff0c;如下图所示&#xff1a; 最初的解决方案是采用富文本编辑器&#xff0c;把所有句段信息都用HTML标签包裹&#xff0c;操作空间比较大&#xff0c;页面上需要的功能几乎都可以实现&#xff0c;但是由…

串口通讯接口类型:TTL、RS232和RS485(电平标准)

串口通讯接口类型&#xff1a;TTL、RS232和RS485 在串口通信中&#xff0c;常用的接口类型包括TTL、RS-232和RS-485&#xff0c;TTL、RS-232、RS422、RS-485是指的电平标准(电信号)。 通信协议规定了数据传输的规则和格式&#xff0c;包括数据的起始位、停止位、数据位数、校…

docker 搭建jenkins

1、拉取镜像 docker pull jenkins/jenkins:2.4162、创建文件夹 mkdir -p /home/jenkins_mount chmod 777 /home/jenkins_mount3、运行并构建容器 docker run --restartalways -d -p 10240:8080 -p 10241:50000 -v /home/jenkins_mount:/var/jenkins_home -v /etc/localtime:…

从零开始构建基于YOLOv5的目标检测系统

本博文从零开始搭建基于YOLOv5模型的目标检测系统&#xff08;具体系统参考本博主的其他博客&#xff09;&#xff0c;手把手保姆级完成环境的搭建。 &#xff08;1&#xff09;首先Windows R输入cmd命令后打开命令窗口&#xff0c;进入项目目录&#xff0c;本博文以野生动物…

无涯教程-jQuery - jQuery.ajaxSetup( options )方法函数

jQuery.ajaxSetup(options)方法为将来的AJAX请求设置全局设置。 jQuery.ajaxSetup( options ) - 语法 $.ajaxSetup( options ) 这是此方法使用的所有参数的描述- options - 一组配置Ajax请求的键/值对&#xff0c;所有选项都是可选的。 Sr.No.Option & Remark1 asy…

Stack

文章目录 定义分类静态栈动态栈 算法应用 定义 在静态内存当中分配的叫做栈&#xff0c;在动态内存中分配的叫做堆。 **红色椭圆圈当中的就是在栈中分配的&#xff0c;蓝色下划线的就是在堆里分配的。**栈和堆表示的是分配数据的一种方式。静态局部变量是通过压栈和出栈来分配…

网络安全行业相关证书

一&#xff1a;前言 对于考证这个话题&#xff0c;笔者的意见是&#xff1a;“有比没有好&#xff0c;有一定更好&#xff0c;但不一定必须&#xff1b;纸上证明终觉浅&#xff0c;安全还得实力行”。很多人对于各种机构的考证宣传搞得是云里雾里&#xff0c;不知道网络安全行业…

【Java练习题汇总】《第一行代码JAVA》网络编程篇集合体系篇,汇总Java练习题——Socket 与ServerSocket、List和Set、Map~

Java练习题 网络编程篇&集合体系篇 1️⃣ 网络编程篇&集合体系篇 1️⃣ 网络编程篇&集合体系篇 一、填空题 在类集中存放单值的最大父接口是___________ &#xff0c;存放一对值的最大父接口是___________ 。___________ 接口保存的数据是不允许重复的&#xff…

c语言复合赋值符和运算符的优先级问题

结论&#xff1a; 复合赋值符的优先级小于运算符 【练习1】 a * a / b的运算顺序是什么&#xff1f; a / b * a 【练习2】 x / 3 2 * 3 2 / 3 6 2 x 0

使用os库操作目录和文件

1. 获取本机操作系统的分隔符 # 导入os库 import os # 获取本机操作系统的分隔符 print(os.sep) 2. 获取本机操作系统的类型 如果是windows&#xff0c;是nt。 # 导入os库 import os # 获取本机操作系统的类型 print(os.name) 3. 获取当前的工作目录路径 # 导入os库 import…

RL vs 最优控制:用于轨迹跟踪的 LQR(使用 Python 代码)

一、说明 在本博客系列中&#xff0c;我们将了解最优控制的经典方法&#xff0c;这些方法在某种程度上为强化学习等更熟悉的主题奠定了坚实的基础。这两个领域之间存在着不可避免的共同边界&#xff0c;本系列旨在提出这些最优控制的形式化方法&#xff0c;作为强化学习方法的有…

[内网渗透]SUID提权

文章目录 [内网渗透]SUID提权0x01.什么是SUID&#xff1f;0x02.如何设置SUID&#xff1f;0x03.查找属主为root的SUID文件0x04.进行SUID提权1.find提权2.vim/vi/vim.tiny 以root权限修改文件3.bash提权4.less/more执行系统命令5.nano以root权限修改文件6.awk执行系统命令7.cp以r…

CHD6.2.1集群 Hive开启Iceberg

下载jar包 https://repo1.maven.org/maven2/org/apache/iceberg/iceberg-hive-runtime/1.0.0/iceberg-hive-runtime-1.0.0.jar 存放在/opt/cloudera/parcels/CDH/lib/hive/auxlib/ CDH集群修改hive配置 选择xml格式 粘贴即可 <property><name>iceberg.engine.hi…