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

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。打印结果如下:

测试正常。

相关推荐
leoZ2313 小时前
本地跑大模型实战(七):llama.cpp 性能调优,让推理更快更省
java·人工智能·spring·生成对抗网络·语言模型·自然语言处理·llama
大模型momo5 小时前
Spring AI 实战:多 Agent 协作实战 —— 分工拆解复杂旅游行程任务
人工智能·spring·ai·agent·旅游
小程故事多_805 小时前
从A2C、TRPO、PPO到GRPO,强化学习策略梯度算法完整演进与大模型落地实战解析
人工智能·算法
2601_956121977 小时前
二分算法(知识点+题目)
c++·算法
江南十四行8 小时前
Spring框架核心(上)——IoC控制反转与DI依赖注入详解
java·后端·spring
AndrewHZ10 小时前
【LLM技术全景】阶段总结:技术原理篇核心知识回顾
人工智能·深度学习·算法·语言模型·大模型·llm·芯片开发
小星星闪亮登场11 小时前
2026萌新联赛第三场-- (郑州轻工业大学)
数据结构·c++·经验分享·算法·贪心算法·排序算法·深度优先
IKUN家族11 小时前
Spring MVC(四)
java·spring·mvc
冻柠檬飞冰走茶11 小时前
PTA基础编程题目集 7-8超速判断(C++语言实现)
开发语言·数据结构·c++·算法
BullSmall11 小时前
Another Redis Desktop Manager(ARDM)下载指南
数据库·redis·缓存