开源仓库:unittest
基本概念
可以将顺序队列看作是排队买奶茶,新来的人站在队尾(rear / tail),买完奶茶后队伍头的0号位的人走了,那原来排在第1号位的人成为新的队伍头(front / head)。但这里需要注意,为了降低时间复杂度,提高效率,实际编程时,是通过改变指针指向来实现顺序队列逻辑的,这也是为什么使用顺序队列会出现 [ 假溢出 ] 问题。

新顾客到来,往后排:8号新顾客要排到7号顾客的后面。8号是位置,顾客是站在8号位置上的人。对应入队代码就可以写为:
c
tail = (tail + 1); //8号顾客成为队尾,tail在代码里代表地址(8号)。
data[tail] = value; //value就是顾客这个人。
size++; //size就是顾客人数增加1个。
0号顾客在拿到奶茶后,就离开了,1号顾客排到了队首位置。同样,1号是位置,顾客是站在1号位置上的人。对应出队代码可以写为:
c
head = (head + 1); //假设奶茶店最多能站10个人,1号顾客成为队首,head在代码里代表地址(1号)。
size--; //顾客走了,人数减少1个。
随着新顾客的不断到来,奶茶店的10个位置都满了。对应队满代码可以写为:
c
return (size = 10); //简单的统计了一下人数10人。
顾客们都拿到了自己的奶茶,都离开了。对应的队空代码可以写为:
c
return (size = 0); ////简单的统计了一下人数0人。
上面就是顺序队列代码开发思想的由来,这样做可以将数据得到缓存,不用那么着急的将数据读走。就像奶茶店老板一样,原来店小,只能排队站2个人,新来的3号顾客会失望的离开。如果不想失去3号顾客,老板就得加块动作,尽快让队首的顾客拿到奶茶离开。现在,店面进行了扩建,能排队站10个人了,顾客也愿意等了。老板就可以从容的制作奶茶。
一个实例
顺序队列是用数组(顺序存储结构)实现的队列,遵循队列「先进先出(FIFO, First In First Out)」的核心规则 ------ 数据从队尾入队,从队头出队,就像日常排队买东西,先到的人先结账。我们以一个实例进行演示。
- queue_array.h
头文件定义一个结构体,结构体有成员变量:数据数组、头指针、尾指针、队列元素计数器。一个完整的顺序队列就定义完成了。
c
#ifndef __QUEUE_ARRAY_H
#define __QUEUE_ARRAY_H
#ifdef __cplusplus
extern "C" {
#endif
// 队列
#define MAX_SIZE 10
typedef struct ArrayQueue
{
int data[MAX_SIZE];
int front; // 定义头指针
int rear; // 定义尾指针
int size; // 队列元素计数器
} ArrayQueue;
void initQueue( ArrayQueue *q);
int isEmpty( ArrayQueue *q);
int isFull( ArrayQueue *q);
void enqueue( ArrayQueue *q, int value);
int dequeue( ArrayQueue *q);
int getQueueSize( ArrayQueue *q);
void printQueue( ArrayQueue *q);
#ifdef __cplusplus
}
#endif
#endif /* __QUEUE_ARRAY_H */
- queue_array.c
源文件实现具体操作,包括:队列初始化、入队操作、出队操作、队满判断、队空判断。这样,顺序队列的基本功能就有了,可以作为模块化设计的一部分,被调用。
c
#include "queue_array.h"
#include <stdio.h>
#include <stdlib.h>
/**
* ************************************************
* @brief 初始化队列
* @param q Param...
*/
void initQueue(ArrayQueue *q)
{
q->front = 0;
q->rear = -1;
q->size = 0;
}
/**
* ************************************************
* @brief 判断队列是否为空
* @param q Param...
* @return int
* ************************************************
*/
int isEmpty(ArrayQueue *q)
{
return q->size == 0;
}
/**
* ************************************************
* @brief 判断队列是否已满
* @param q Param...
* @return int
* ************************************************
*/
int isFull(ArrayQueue *q)
{
return q->size == MAX_SIZE;
}
/**
* ************************************************
* @brief 入队操作
* @param q Param...
* @param value Param...
*/
void enqueue(ArrayQueue *q, int value)
{
if (isFull(q))
{
return;
}
q->rear = (q->rear + 1);
q->data[q->rear] = value;
q->size++;
}
/**
* ************************************************
* @brief 出队操作
* @param q Param...
* @return int
* ************************************************
*/
int dequeue(ArrayQueue *q)
{
if (isEmpty(q))
{
return -1;
}
int tmp = q->data[q->front];
q->front = (q->front + 1);
q->size--;
return tmp;
}
/**
* ************************************************
* @brief Get the Queue Size object
* @param q Param...
* @return int
* ************************************************
*/
int getQueueSize(ArrayQueue *q)
{
return q->size;
}
/**
* ************************************************
* @brief 遍历打印队内元素
* @param q Param...
*/
void printQueue(ArrayQueue *q)
{
if (isEmpty(q))
{
return;
}
int i = q->front;
for (int j = 0; j < q->size; j++)
{
// printf("%d ", q->data[i]);
i = (i + 1) % MAX_SIZE;
}
}
实例测试
功能有了,就可以借助于GoogleTest单元测试框架,完成顺序队列的测试工作,验证一下顺序队列的代码实现逻辑是否有问题。
c
#define GOOGLE_GLOG_DLL_DECL
#define GLOG_NO_ABBREVIATED_SEVERITIES
#define GLOG_EXPORT
#define GLOG_NO_EXPORT
#include <gtest/gtest.h>
#include <gtest/stub.h>
#include <glog/logging.h>
#include <iostream>
#include "queue_array.h"
using namespace std;
using namespace std::chrono_literals;
/*-----------------BEGIN----------------*/
void printQueueArray(ArrayQueue *q)
{
if (isEmpty(q))
{
return;
}
int i = q->front;
for (int j = 0; j < q->size; j++)
{
LOG(INFO) << "the queue data value: " << q->data[i];
i = (i + 1) % MAX_SIZE;
}
}
/**
* ************************************************
* @brief 顺序队列测试函数
* @return int
* ************************************************
*/
int queue_array_main(void)
{
ArrayQueue q;
initQueue(&q);
// 往队列内插入元素
enqueue(&q, 10);
enqueue(&q, 20);
enqueue(&q, 30);
enqueue(&q, 40);
printQueueArray(&q);
LOG(INFO) << "the queue size value: " << getQueueSize(&q);
dequeue(&q);
printQueueArray(&q);
LOG(INFO) << "the queue size value: " << getQueueSize(&q);
return 0;
}
TEST(TestSuite0, TEST2){
LOG(INFO) << "\r\nUT >>> queue_array_main";
queue_array_main();
}
/*------------------END-----------------*/
int gtest_main(int argc, char *argv[]){
google::InitGoogleLogging("UNITTEST");
google::SetStderrLogging(google::GLOG_INFO);
google::SetLogDestination(google::GLOG_INFO, ".//log//INFO_");
google::EnableLogCleaner(2);
//init global variable
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
google::ShutdownGoogleLogging();
}
测试报告
输出报告可以很清晰的看到顺序队列的数据结构逻辑实现结果。
powershell
Log file created at: 2026/02/12 18:04:27
Running on machine: DESKTOP-J6Q1P85
Running duration (h:mm:ss): 0:00:00
Log line format: [IWEF]yyyymmdd hh:mm:ss.uuuuuu threadid file:line] msg
I20260212 18:04:27.791738 13304 test_case.cpp:102]
UT >>> queue_array_main
I20260212 18:04:27.797263 13304 test_case.cpp:47] the queue data value: 10
I20260212 18:04:27.797263 13304 test_case.cpp:47] the queue data value: 20
I20260212 18:04:27.798266 13304 test_case.cpp:47] the queue data value: 30
I20260212 18:04:27.798266 13304 test_case.cpp:47] the queue data value: 40
I20260212 18:04:27.798266 13304 test_case.cpp:67] the queue size value: 4
I20260212 18:04:27.798266 13304 test_case.cpp:47] the queue data value: 20
I20260212 18:04:27.798266 13304 test_case.cpp:47] the queue data value: 30
I20260212 18:04:27.798266 13304 test_case.cpp:47] the queue data value: 40
I20260212 18:04:27.798266 13304 test_case.cpp:70] the queue size value: 3
I20260212 18:04:27.801265 13304 test_case.cpp:110]