天天快资讯丨基于C语言的泛类型循环队列
时间:2023-06-24 01:14:03来源:博客园

循环队列多用于通信数据缓存中,尤其是在双方设备接收数据与处理数据不同步的情况下,使用循环队列先缓存通信数据,然后按照时间戳数据出队作出相应的处理,是一种比较合适的做法,在嵌入式编程中亦是如此。使用循环队列的数据结构可以实现上述功能,在一些低端的编程平台手写一个循环队列既满足了功能需求又不会开销太多资源。

设计思想

实现一个队列可以使用顺序表(数组)或链表实现。前者访问速度块,但是要占用连续的存储空间,适用于内存小但是速度要求较快的存储场合。后者访问速度慢但是基于链表式的结构,可以使用碎片内存,适用内存大,速度慢的场合。本文面向的编程平台是中低端MCU,时钟主频、RAM空间有限,因此选用顺序表来实现循环队列。关于顺序表实现循环队列的文章网上又很多,但是大多都基于一个明确的数据类型,如果在一个工程中两种完全不同的数据类型都想使用循环队列的数据结构就会使得相同的代码出现多次,导致代码冗余。泛类型循环队列的思想是将顺序表中每个节点都看作一个uint8_t*类型的指针,在队列初始化时,要传入节点占用空间字节数,对每个节点malloc一个相应的存储空间,当数据入队时使用memcpy函数将源地址字节数拷贝到目标地址即可,队列数据表的结构有点类似于哈希表,操作与定类型循环队列类似。

代码实现

队列实现包含两个文件:queue.h和queue.cqueue.h:使用枚举自定义BOOL类型,C99标准之后包含stdbool.h可使用标准布尔型


(资料图片)

typedef enum {    FALSE,    TRUE } BOOL;

宏定义顺序表中的节点类型

#define NODTETYPE uint8_t*

定义循环队列结构体

typedef struct Queue{uint32_t capacity;     // 队列总容量uint32_t size;         // 当前队列大小uint32_t front;        // 队列头节点uint32_t rear;         // 队列尾节点  NODTETYPE* data;         //存储节点的顺序表} Queue;

接口函数

/* 初始化一个队列 */BOOL init_queue(Queue *queue,uint32_t _capacity,uint32_t DataWidth);/* 数据入队 */BOOL en_queue(Queue* _queue, NODTETYPE _data,uint32_t DataWidth);/*队列判空*/BOOL isempty_queue(Queue* _queue);/*队列判满*/BOOL isfull_queue(Queue* _queue);/* 数据出队 */NODTETYPE de_queue(Queue* _queue);/* 清空队列 */void clear_queue(Queue* _queue);

queue.c队列初始化,此处必须传入节点的数据占用字节数DataWidth,注意可用队列容量总是比传入参数_capacity小一,因为要判空和判满。

BOOL init_queue(Queue *queue,uint32_t _capacity,uint32_t DataWidth){    NODTETYPE *buff= (NODTETYPE*)malloc(_capacity*sizeof(NODTETYPE));    if(buff==NULL)        return FALSE;    for(int i=0;i<_capacity;i++)    {        NODTETYPE NodeTemp=(NODTETYPE)malloc(DataWidth);        if(NodeTemp==NULL)            return FALSE;        else            buff[i]=NodeTemp;    }    queue->data=buff;    queue->capacity = _capacity;    queue->size = 0;    queue->front = 0;      queue->rear = 0;    return TRUE;}

数据节点入队

BOOL en_queue(Queue* _queue, NODTETYPE _data,uint32_t DataWidth){    BOOL isFull;    isFull = isfull_queue(_queue);    if (isFull == TRUE)    {        _queue->front = (_queue->front + 1) % _queue->capacity;    }    memcpy(_queue->data[_queue->rear], _data,DataWidth);    _queue->rear = (_queue->rear + 1) % _queue->capacity;    _queue->size++;    return isFull;}

数据节点出队

NODTETYPE de_queue(Queue* _queue){    if (isempty_queue(_queue))         return NULL;    NODTETYPE result = _queue->data[_queue->front];    _queue->front = (_queue->front + 1) % _queue->capacity;    _queue->size--;    return result;}

队列清空,但是不释放存储空间

void clear_queue(Queue* _queue){    _queue->front = _queue->rear = 0;    _queue->size = 0;}

队列判空

BOOL isempty_queue(Queue* _queue){if (_queue->front == _queue->rear)return TRUE;elsereturn FALSE;}

队列判满

BOOL isfull_queue(Queue* _queue){if ((_queue->rear + 1) % _queue->capacity == _queue->front)return TRUE;elsereturn FALSE;}

队列清空并释放内存

void release_queue(Queue* _queue){    for(int i=0;i<_queue->capacity;i++)    {        free(_queue->data[i]);        _queue->data[i]=NULL;    }    clear_queue(_queue);    free(_queue);    _queue = NULL;}

调用时入队时,要先将节点数据类型强制转化为uint8_t类型,传入形参,出队时获取一个uint8_t的指针,然后强制转换为定义的节点类型指针,之后就可以访问到出队节点的数据,举例如下:

#include "queue.h"typedef  struct ClassTest  //定义测试类型{    uint8_t a;    uint16_t b;    uint32_t c;}ClassTest;int main(int argc, char *argv[]){    Queue queue1;    Queue queue2;    init_queue(&queue1,100,sizeof (ClassTest));    init_queue(&queue2,200,1);  //测试队列2就用uint8_t    int i=0;    uint8_t queue1_node=0;    ClassTest queue2_node={0,0,0};    while(isfull_queue(&queue1)==FALSE)    {        queue1_node=i++;        en_queue(&queue1,&queue1_node,sizeof (queue1_node));    }    i=0;    while(isfull_queue(&queue2)==FALSE)    {        queue2_node.a=i++;        queue2_node.b=2*i;        en_queue(&queue2,(uint8_t*)(&queue2_node),sizeof (queue2_node));    }    while(isempty_queue(&queue1)==FALSE)    {        NODTETYPE node=de_queue(&queue1);        printf("%d;",*((uint8_t*)(node)));    }    while(isempty_queue(&queue2)==FALSE)    {        NODTETYPE node=de_queue(&queue2);        prinf("%d;",((ClassTest*)(node))->b);    }}

标签:

最新
  • 天天快资讯丨基于C语言的泛类型循环队列

    循环队列多用于通信数据缓存中,尤其是在双方设备接收数据与处理数据不

  • 天天热讯:新道义责任论_关于新道义责任论简介

    1、新道义责任论是西方现代押法学中关于刑事责任本质的学说。2、以相对

  • 天天观速讯丨经济日报携手京东发布数据——新口味粽子受欢迎

    经济日报携手京东发布数据——新口味粽子受欢迎---数据来源京东消费及

  • 热推荐:蒯纪闻中柱,穆罕穆德最后时刻进球,国足U17队0-1沙特U17

    半场战罢,U17中国队暂时以0-1落后沙特阿拉伯U17。在第45分钟的比赛中

  • 环球速递!银川市市长:向遇难者表示沉痛哀悼,向全市人民表示深深的歉意

    6月21日20时40分许,宁夏银川市兴庆区一烧烤店发生燃气爆炸。目前爆炸

  • 官方:37岁波黑前锋哲科加盟土超费内巴切,据悉双方签约2年-天天热议

    官方:37岁波黑前锋哲科加盟土超费内巴切,据悉双方签约2年,欧元,波黑,

  • 天天快报!今年高考志愿这样填报

    东南网6月21日报道(福建日报记者储白珊)针对连日来考生及家长对我省

  • 机油尺怎么插回去 机油尺到什么位置算是正常 当前动态

    机油尺在用完后,用毛巾或者纸巾将其擦拭干净,然后直接插进发动机的机

  • 焦点快看:断纹液和冻干片能去皱吗?

    断纹液和冻干片都是常见的美容产品,但它们是否能去皱呢?答案是:可以

  • 郑渝高铁开通一周年 重庆段发送旅客1900万人次|报资讯

    6月20日,郑渝高铁将开通运营满一周年。据中国铁路成都局集团有限公

  • 护理信息系统的内容包括什么? 护理信息系统的发展具体是如何的呢? 环球讯息

    护理信息系统的内容包括什么?护理信息系统是一个可以迅速收集、大量

  • 快资讯丨胡辣汤的做法大全视频播放(胡辣汤的做法大全)

    辣汤的做法大全视频播放,胡辣汤的做法大全这个问题很多朋友还不知道,

  • 肾功能4项检查什么?肾功能检查多久出结?

    肾功能4项的检查,在每个医疗单位的项目可能有所不同,但是通常很多

  • 股票被套怎么办?股票连续跌停钱都去哪了?-全球新资讯

    股票被套怎么办?1、判断趋势。投资者应该判断股票的走势是处于一个

  • [路演]金杨股份:公司是国内领先的电池精密结构件及材料制造商之一

    2023年6月16日下午,金杨股份(301210)首次公开发行股票并在创业板上

  • 上海华山医院整形美容科专家哪个好 每日快看

    华山医院是一家很不错的整形医院,这家医院从成立的时候就是饱受很多爱

  • 旅游
    • 全球热头条丨史上最强宗主全文阅读_史上最强宗主

    • 新资讯:2023海口桂林洋热带农业公园端午节怎么玩?

    • 深圳职业技术大学首批本科招生!6大专业共招200人 今日热门

    • 全球热文:宁波市鄞州区发布首条探寻“科学家精神”青少年研学线路