数据结构篇 - 顺序队列

开源仓库: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] 
相关推荐
白中白121382 小时前
算法题-14
数据结构·算法·leetcode
plus4s2 小时前
2月13日(73-75题)
数据结构·c++·算法
仰泳的熊猫3 小时前
题目1465:蓝桥杯基础练习VIP-回形取数
数据结构·c++·算法·蓝桥杯
blackicexs3 小时前
第四周第五天
数据结构·算法
重生之后端学习3 小时前
98. 验证二叉搜索树
java·数据结构·后端·算法·职场和发展
菜鸡儿齐3 小时前
leetcode-移动零
数据结构·算法·leetcode
紫陌涵光3 小时前
54. 替换数字(第八期模拟笔试)
数据结构·c++·算法
_Twink1e3 小时前
[算法竞赛]二、链表
数据结构·算法·链表
!停4 小时前
数据结构二叉树—堆(2)&链式结构(上)
数据结构·算法