C语言队列实现参考示例

C语言队列实现参考示例

目录

前言

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

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

1 代码实现

1.1 实现方案

我这里主要使用C语言实现一个通用的循环队列,示意图如下:

先划分一块缓存用来存放队列的数据,然后通过头指针和尾指针,分别指向队列的第一个元素和最后一个元素,当数据入队时,尾指针后移,当数据出队时,头指针后移,从而实现一个闭环。

注:队列中的元素并不是某个特定类型的变量,它可以是整形,可以是数组,也可以是结构体,也就是说这是一个通用的框架。

1.2 代码编写

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

c 复制代码
#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文件):

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;
}

使用示例:

c 复制代码
/* 元素为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语言实现队列的方法就介绍到这里,如果你们有什么问题,欢迎评论区留言。

如果这篇文章能够帮到你,就...懂的。

相关推荐
雯0609~1 小时前
c#:winform调用bartender实现打印(学习整理笔记)
开发语言·c#
胜天半子_王二_王半仙2 小时前
c++源码阅读__smart_ptr__正文阅读
开发语言·c++·开源
Ocean☾3 小时前
C语言-详细讲解-P1217 [USACO1.5] 回文质数 Prime Palindromes
c语言·数据结构·算法
沐泽Mu3 小时前
嵌入式学习-C嘎嘎-Day08
开发语言·c++·算法
Non importa3 小时前
汉诺塔(hanio)--C语言函数递归
c语言·开发语言·算法·学习方法
LinuxST3 小时前
27、基于Firefly-rk3399中断休眠唤醒实验(按键中断)
linux·开发语言·stm32·嵌入式硬件
Tony_long74833 小时前
Python学习——猜拳小游戏
开发语言·python·学习
跳动的梦想家h3 小时前
黑马点评 秒杀下单出现的问题:服务器异常---java.lang.NullPointerException: null(已解决)
java·开发语言·redis
ac-er88883 小时前
PHP 二分法查找算法
开发语言·算法·php
流着口水看上帝3 小时前
JavaScript完整原型链
开发语言·javascript·原型模式