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

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

测试正常。

相关推荐
哭哭啼7 分钟前
Redis环境部署(主从模式、哨兵模式、集群模式)
数据库·redis·缓存
醉颜凉26 分钟前
【NOIP提高组】潜伏者
java·c语言·开发语言·c++·算法
lapiii35835 分钟前
图论-代码随想录刷题记录[JAVA]
java·数据结构·算法·图论
RainbowSea38 分钟前
4. Spring Cloud Ribbon 实现“负载均衡”的详细配置说明
java·spring·spring cloud
Dontla2 小时前
Rust泛型系统类型推导原理(Rust类型推导、泛型类型推导、泛型推导)为什么在某些情况必须手动添加泛型特征约束?(泛型trait约束)
开发语言·算法·rust
Ttang232 小时前
Leetcode:118. 杨辉三角——Java数学法求解
算法·leetcode
喜欢打篮球的普通人2 小时前
rust模式和匹配
java·算法·rust
java小吕布2 小时前
Java中的排序算法:探索与比较
java·后端·算法·排序算法
win x2 小时前
链表(Linkedlist)
数据结构·链表