数据结构:基于数组实现简单的数据缓存区(简单队列)

1 前言

在我们使用CAN或者以太网调试时,经常需要缓存最近n次收到的数据,以便于我们对数据进行分析。

实现这一想法我们很容易就会想到队列,队列就是一种先进先出的数据结构,之前在《数据结构:基于数组的环形队列(循环队列)实现》介绍了基于数组的环形队列(循环队列)的实现,使用到了头尾2个指针,根据头尾指针的关系其实我们可以只使用尾指针就实现循环队列。

下面介绍一种只使用尾指针实现简单的数据缓存区(简单队列)的方法。

2 简单队列实现

2.1 简单队列的定义

c 复制代码
#define MAX_DATA_NO 10   // 数据存储量
#define MAX_DATA_BUFF 10 // 数据缓存区大小
typedef struct
{
    int fullFlg;                              /* 队列满标志 0-未满 1-满*/
    int dataTail;                             /* 队列尾指针 */
    int dataTotalCount;                       /* 总共数据量 */
    int dataLen[MAX_DATA_NO];                 /* 数据长度 */
    int dataBuff[MAX_DATA_NO][MAX_DATA_BUFF]; /* 数据缓存区 */
} s_queue_t;

2.2 初始化简单队列

c 复制代码
/**
 * @brief 初始化简单队列
 *
 * @param sQueue 简单队列地址
 */
void init_squeue(s_queue_t *sQueue)
{
    sQueue->fullFlg = 0;
    sQueue->dataTail = 0;
    sQueue->dataTotalCount = 0;
}

初始化简单队列的操作很简单,就是将尾指针、队列满标志、接收数据计数全部清零。

2.3 添加数据到队列

c 复制代码
/**
 * @brief 添加数据到简单队列
 *
 * @param sQueue 简单队列地址
 * @param dataLen 数据长度
 * @param dataBuff 数据缓存区
 */
void add_data_to_squeue(s_queue_t *sQueue, int dataLen, int *dataBuff)
{
    int i;
    sQueue->dataLen[sQueue->dataTail] = dataLen;
    for (i = 0; i < dataLen; i++)
    {
        sQueue->dataBuff[sQueue->dataTail][i] = dataBuff[i];
    }
    sQueue->dataTail++;
    if (sQueue->dataTail >= MAX_DATA_NO)
    {
        sQueue->dataTail = 0;
    }
    sQueue->dataTotalCount++;
    if (sQueue->dataTotalCount >= MAX_DATA_NO)
    {
        sQueue->fullFlg = 1;
    }
}

添加数据到队列就是将数据、数据长度写到尾指针指向的数据缓存区,然后将尾指针后移一位(超出缓存区容量时跳转到0)。

2.4 简单队列数据打印

c 复制代码
/**
 * @brief 打印简单队列数据
 *
 * @param dataHead 数据头
 * @param dataNum 数据数量
 * @param sQueue 简单队列地址
 */
void printf_squeue_data(int dataHead, int dataNum, s_queue_t *sQueue)
{
    int p;
    int i, j, k = 0;
    printf("Num   Len  Data\r\n");
    for (i = 0; i < dataNum; i++)
    {
        p = dataHead + i;
        if (p >= MAX_DATA_NO)
        {
            p -= MAX_DATA_NO;
        }
        printf("%-3d   %-2d   ", ++k, sQueue->dataLen[p]);
        for (j = 0; j < sQueue->dataLen[p]; j++)
        {
            printf("%d ", sQueue->dataBuff[p][j]);
        }
        printf("\r\n");
    }
}
/**
 * @brief 简单队列数据处理
 *
 * @param sQueue 队列地址
 */
void squeue_data_pro(s_queue_t *sQueue)
{
    int i, j;
    int dataHead, dataTail;
    printf("Total data count : %d\r\n", sQueue->dataTotalCount);
    if (sQueue->fullFlg != 1)
    {
        printf_squeue_data(0, sQueue->dataTotalCount, sQueue);
    }
    else
    {
        dataHead = sQueue->dataTail;
        printf_squeue_data(dataHead, MAX_DATA_NO, sQueue);
    }
}

简单队列数据打印分为2个部分:

(1)数据解析部分

根据简单队列句柄的队列满标志求得队列头指针值、数据数量。

(2)数据打印部分

根据传入的队列头和数据数量打印队列数据信息。

3 测试

3.1 添加7个数据(队列未满情况)

测试程序如下:

c 复制代码
int main(void)
{
    int i;
    int data[10] = {0, 11, 12, 13, 14, 15, 16, 17, 18, 19};
    s_queue_t sQueue;
    init_squeue(&sQueue);
    for (i = 0; i < 7; i++)
    {
        data[0]++;
        add_data_to_squeue(&sQueue, 10, data);
    }
    squeue_data_pro(&sQueue);
    return 0;
}

向简单队列添加7个数据,首个数据从1-7。打印结果如下:

测试正常。

3.2 添加700个数据(队列满情况)

测试程序如下:

c 复制代码
int main(void)
{
    int i;
    int data[10] = {0, 11, 12, 13, 14, 15, 16, 17, 18, 19};
    s_queue_t sQueue;
    init_squeue(&sQueue);
    for (i = 0; i < 700; i++)
    {
        data[0]++;
        add_data_to_squeue(&sQueue, 10, data);
    }
    squeue_data_pro(&sQueue);
    return 0;
}

向简单队列添加700个数据,首个数据从1-700。打印结果如下:

测试正常。

相关推荐
用户938515635073 小时前
从 O(n²) 到 O(nlogn):一文读懂快速排序的“快”与“妙”
javascript·算法
小七-七牛开发者4 小时前
TokenPilot:让 LLM Agent 长会话成本降 60%+ 的上下文管理
缓存·agent·token·context·上下文·推理成本
To_OC4 小时前
手写快排次次翻车?别死背快排模板了,这才是面试官想听的底层逻辑
javascript·算法·排序算法
饼干哥哥5 小时前
Reddit VOC调研太慢?搭一个AI专家团队半小时洞察任何品类|以猫用饮水机为例
人工智能·算法·ai编程
地平线开发者6 小时前
Transformer模型部署之性能优化指南
算法
地平线开发者7 小时前
人在途中:从“编译失败”到“模型可落地”——CUDA 自定义算子
算法·自动驾驶
半个落月10 小时前
从递归到快速排序:用 JavaScript 把分治思想讲明白
javascript·算法·面试
小月土星11 小时前
JavaScript 快速排序:从 pivot、双指针到分治思想
javascript·算法·面试
小月土星11 小时前
JavaScript 递归入门:从 1 到 n 求和,再到数组扁平化
javascript·算法·面试
咖啡八杯1 天前
GoF设计模式——策略模式
java·后端·spring·设计模式