梦想不会自己发光,真正闪耀的是那个为梦狂奔的你。献给知行的孩子们!(Eric.He著)
队列是数据结构中经典的先进先出(FIFO, First In First Out)线性结构,就像日常生活中的排队买票——先排队的人先购票,后排队的人后购票。本教程基于数组实现的队列,从核心原理、代码结构到实战使用,全面讲解队列的原理与实现,功能包含入队、出队、获取队列头元素、获取队列尾元素等核心功能。
| 操作名称 | 功能描述 | 时间复杂度 |
|---|---|---|
| 入队 | 将指定元素添加到队尾,队列满时抛出异常或返回失败标识 | O(1) |
| 出队 | 从队头移除并返回元素,队列为空时抛出异常或返回失败标识 | O(1) |
| 判空 | 判断队列是否为空,返回布尔值(true = 空,false = 非空) | O(1) |
| 判满 | 判断固定容量队列是否已满,返回布尔值(true = 满,false = 未满)(链式队列无需此操作) | O(1) |
| 获取队头元素 | 查看队头元素的值,不执行移除操作,队列为空时抛出异常或返回无效值 | O(1) |
| 获取队尾元素 | 查看队尾元素的值,不执行移除操作,队列为空时抛出异常或返回无效值 | O(1) |
| 获取队列大小 | 查看队列元素数量,队列为空时返回0 | O(1) |
队列可以采用顺序存储和链式存储两种形式:
每一个节点有二个域,即data数据域、next下一个节点地址。
提供的代码是模板化的队列实现(支持任意类型),采用C++结构体封装,分为头文件(声明)和源文件(实现)两部分,核心结构如下:
| 模块 | 作用 | 关键结构/函数 |
|---|---|---|
| 队列结构体 | 封装所有操作 | ArrayQueue<T>(模板类) |
template <typename T>
struct ArrayQueue{
// ------------------------------------------------------------------------------------------------------
// 私有成员
// 注:私有成员只能在该结构体内部访问调用,外部通过该结构体定义(实例化)的变量(对象)不能访问调用)
//------------------------------------------------------------------------------------------------------
private:
//---------------声明私有成员变量---------------
T data[MAXSIZE]; // 存储数据,可存储字符或整数
int head; // 队列头,初始为-1表示空栈
int tail; // 队列尾,初始为-1表示空栈
int qty; // 用于跟踪队列中的元素数量
//---------------声明私有成员函数---------------
// ------------------------------------------------------------------------------------------------------
// 公共成员
// 注:公共成员能在该结构体内部访问调用,外部通过该结构体定义(实例化)的变量(对象)也能访问调用)
//------------------------------------------------------------------------------------------------------
public:
//---------------声明公共成员函数---------------
// 构造函数:外部通过该结构体定义(实例化)变量(对象)时,自动执行该函数(主要用于初始化成员变量的值)
ArrayQueue() {
head = 0; tail = 0; qty = 0;
for(int i=0;i < MAXSIZE;i++) { data[i] = T(); }
}
int isEmpty();// 判断队列是否为空
int isFull();// 判断队列是否已满
void enQueue(const T& value);// 入队操作(在队列尾入队)
T deQueue();// 出队操作(返回队列头元素,队列空返回-1)
T getHead();// 获取队列头元素(不弹出,队列空返回-1)
T getTail();// 获取队列尾元素(不弹出,队列空返回-1)
int getSize();// 获取队列大小
void print();// 打印队列数据
void destroyQueue();// 销毁整个队列(防止内存泄漏)
// 析构函数:自动销毁队列,避免内存泄漏
~ArrayQueue() {
}
};
int、float、自定义类型等任意类型(需重载比较运算符);template <typename T>
T ArrayQueue<T>::getHead()
{
if (isEmpty()) {
return T();
}
return data[head];
}
template <typename T>
T ArrayQueue<T>::getTail()
{
if (isEmpty()) {
return T();
}
int index = (tail - 1 + MAXSIZE) % MAXSIZE;// 计算队尾元素的真实下标(适配循环队列)
return data[index];
}
template <typename T>
void ArrayQueue<T>::enQueue(const T& value)
{
if (isFull())
{
printf("队列已满!无法入队。\n");
return;
}
data[tail] = value;
tail = (tail + 1) % MAXSIZE; //实现循环队列
qty++;
}
template <typename T>
T ArrayQueue<T>::deQueue()
{
if(isEmpty())
{
printf("队列为空,无法出队。\n");
return T();
}
T value =data[head];
data[head] = T(); // 可选:清空出队的位置
head = (head + 1) % MAXSIZE;
qty--;
return value;
}
#include "ArrayQueue.h"
#include <iostream>
int main() {
ArrayQueue<int> queues;
// 1. 入队测试
printf("\n=== 入队测试 ===\n");
queues.enQueue(1);
queues.enQueue(2);
queues.enQueue(3);
queues.enQueue(4);
queues.enQueue(5);
printf("入队1、2、3、4、5后:\n");
queues.print();
// 2. 出队测试
printf("\n=== 出队测试 ===\n");
printf("出队3次:");
printf("%d ",queues.deQueue());
printf("%d ",queues.deQueue());
printf("%d \n",queues.deQueue());
printf("出队后");
queues.print();
return 0;
}
=== 入队测试 ===
入队1、2、3、4、5后:
队列内容:1 2 3 4 5
队列状态:头指针=0,尾指针=5,元素数量=5
=== 出队测试 ===
出队3次:1 2 3
出队后队列内容:4 5
队列状态:头指针=3,尾指针=5,元素数量=2
#ifndef ENTITYS_H_INCLUDED
#define ENTITYS_H_INCLUDED
//************************************************************************************************************************************************************************
// 自定义类型
//************************************************************************************************************************************************************************
//========================================================================================================================================================================
// 学生结构体(Student)
//========================================================================================================================================================================
struct Student {
int id;// 学号
std::string name;// 姓名
std::string dob;// 出生日期
std::string sex;// 性别
std::string gender;// 民族
std::string address;// 地址
float score;// 入学总分
std::string school;// 学校
std::string team;// 班级
std::string status;// 状态
bool operator<(const Student& other) const { return id < other.id; }
bool operator>(const Student& other) const { return id > other.id; }
bool operator==(const Student& other) const { return id == other.id; }
bool operator!=(const Student& other) const { return id != other.id; }
friend std::ostream& operator<<(std::ostream& os, const Student& s) {
os << "[" << s.id<< ", " << s.name << ", " << s.dob << ", " << s.sex << ", " << s.gender << ", " << s.address << ", " << s.score<< ", " << s.school<< ", " << s.team<< ", " << s.status << "]";
return os;
}
};
//========================================================================================================================================================================
//
// 学生索引结构体(Student)
//
//========================================================================================================================================================================
struct StudentIndex {
int id;// 学号
int row;// 行号
bool operator<(const StudentIndex& other) const { return id < other.id; }
bool operator>(const StudentIndex& other) const { return id > other.id; }
bool operator==(const StudentIndex& other) const { return id == other.id; }
bool operator!=(const StudentIndex& other) const { return id != other.id; }
friend std::ostream& operator<<(std::ostream& os, const StudentIndex& i) {
os << "[" << i.id << ", " << i.row<< "]";
return os;
}
};
//========================================================================================================================================================================
// 迷宫坐标结构体(Pos)
//========================================================================================================================================================================
struct Pos{
int x; //x坐标
int y; //y坐标
int step; //步数
};
//========================================================================================================================================================================
// 打印任务结构体(PrintTask)
//========================================================================================================================================================================
struct PrintTask{
int taskId; // 任务ID
char content[50]; // 打印内容
};
#endif // ENTITYS_H_INCLUDED
#ifndef ARRAYQUEUE_H_INCLUDED
#define ARRAYQUEUE_H_INCLUDED
#include "Entitys.h"
//************************************************************************************************************************************************************************
//
// 类名:数组队列(ArrayQueue)
//
// 概述:一个可复用的数组队列,存储结构采用数组实现,支持任意类型数据(模板泛型)。
//
// 说明:默认队列的最大容量为100,入队出队时间复杂度为O(1)
//
//************************************************************************************************************************************************************************
#define MAXSIZE 100 // 队列的最大容量
//========================================================================================================================================================================
//
// 数组队列结构体(ArrayQueue)
//
//========================================================================================================================================================================
template <typename T>
struct ArrayQueue{
// ------------------------------------------------------------------------------------------------------
// 私有成员
// 注:私有成员只能在该结构体内部访问调用,外部通过该结构体定义(实例化)的变量(对象)不能访问调用)
//------------------------------------------------------------------------------------------------------
private:
//---------------声明私有成员变量---------------
T data[MAXSIZE]; // 存储数据,可存储字符或整数
int head; // 队列头,初始为-1表示空栈
int tail; // 队列尾,初始为-1表示空栈
int qty; // 用于跟踪队列中的元素数量
//---------------声明私有成员函数---------------
// ------------------------------------------------------------------------------------------------------
// 公共成员
// 注:公共成员能在该结构体内部访问调用,外部通过该结构体定义(实例化)的变量(对象)也能访问调用)
//------------------------------------------------------------------------------------------------------
public:
//---------------声明公共成员函数---------------
// 构造函数:外部通过该结构体定义(实例化)变量(对象)时,自动执行该函数(主要用于初始化成员变量的值)
ArrayQueue() {
head = 0; tail = 0; qty = 0;
for(int i=0;i < MAXSIZE;i++) { data[i] = T(); }
}
int isEmpty();// 判断队列是否为空
int isFull();// 判断队列是否已满
void enQueue(const T& value);// 入队操作(在队列尾入队)
T deQueue();// 出队操作(返回队列头元素,队列空返回-1)
T getHead();// 获取队列头元素(不弹出,队列空返回-1)
T getTail();// 获取队列尾元素(不弹出,队列空返回-1)
int getSize();// 获取队列大小
void print();// 打印队列数据
void destroyQueue();// 销毁整个队列(防止内存泄漏)
// 析构函数:自动销毁队列,避免内存泄漏
~ArrayQueue() {
}
};
#endif // ARRAYQUEUE_H_INCLUDED
#include <iostream>
#include"ArrayQueue.h"
//**********************实现公有成员函数**********************
// 判断队列是否为空
template <typename T>
int ArrayQueue<T>::isEmpty()
{
return qty == 0;
}
// 判断队列是否已满
template <typename T>
int ArrayQueue<T>::isFull()
{
return qty == MAXSIZE;
}
// 入队操作(在队列尾入队)
template <typename T>
void ArrayQueue<T>::enQueue(const T& value)
{
if (isFull())
{
printf("队列已满!无法入队。\n");
return;
}
data[tail] = value;
tail = (tail + 1) % MAXSIZE; //实现循环队列
qty++;
}
// 出队操作(返回队列头元素)
template <typename T>
T ArrayQueue<T>::deQueue()
{
if(isEmpty())
{
printf("队列为空,无法出队。\n");
return T();
}
T value =data[head];
data[head] = T(); // 可选:清空出队的位置
head = (head + 1) % MAXSIZE;
qty--;
return value;
}
// 获取队列头元素(不弹出)
template <typename T>
T ArrayQueue<T>::getHead()
{
if (isEmpty()) {
return T();
}
return data[head];
}
// 获取队列尾元素(不弹出)
template <typename T>
T ArrayQueue<T>::getTail()
{
if (isEmpty()) {
return T();
}
int index = (tail - 1 + MAXSIZE) % MAXSIZE;// 计算队尾元素的真实下标(适配循环队列)
return data[index];
}
// 获取队列大小
template template <typename T>
int ArrayQueue<T>::getSize()
{
return qty;
}
// 打印队列数据(仅遍历有效元素,不修改任何指针)
template <typename T>
void ArrayQueue<T>::print()
{
if (isEmpty()) {
printf("队列内容:空\n");
return;
}
printf("队列内容:");
// 遍历队列中实际存在的 qty 个元素
for (int i = 0; i < qty; i++) {
// 计算第i个有效元素的索引(适配循环队列)
int index = (head + i) % MAXSIZE;
printf("%d ", data[index]);
}
printf("\n");
// 可选:打印队列状态(便于调试)
printf("队列状态:头指针=%d,尾指针=%d,元素数量=%d\n", head, tail, qty);
}
// 显式实例化常用类型(避免链接错误,可选)
template class ArrayQueue<int>;
template class ArrayQueue<char>;
template class ArrayQueue<float>;
template class ArrayQueue<std::string>;
template class ArrayQueue<Student>; // 新增:显式实例化Student类型
template class ArrayQueue<Pos>; // 新增:显式实例化Pos类型
template class ArrayQueue<PrintTask>; // 新增:显式实例化PrintTask类型
#include "ArrayQueue.h"
#include <iostream>
#include <string>
int main() {
ArrayQueue<int> queues;
// 1. 入队测试
printf("\n=== 入队测试 ===\n");
queues.enQueue(1);
queues.enQueue(2);
queues.enQueue(3);
queues.enQueue(4);
queues.enQueue(5);
printf("入队1、2、3、4、5后:\n");
queues.print();
// 2. 出队测试
printf("\n=== 出队测试 ===\n");
printf("出队3次:");
printf("%d ",queues.deQueue());
printf("%d ",queues.deQueue());
printf("%d \n",queues.deQueue());
printf("出队后");
queues.print();
return 0;
}
=== 入队测试 ===
入队1、2、3、4、5后:
队列内容:1 2 3 4 5
队列状态:头指针=0,尾指针=5,元素数量=5
=== 出队测试 ===
出队3次:1 2 3
出队后队列内容:4 5
队列状态:头指针=3,尾指针=5,元素数量=2
模板类型约束:
</>/==运算符(内置类型如int/string默认支持,自定义类型需重载);<<运算符(打印输出时使用)。显式实例化:代码末尾的template class LinkedQueue<int>;等显式实例化,避免链接错误,新增类型需补充显式实例化。
本教程通过代码解析和实战示例,覆盖了队列的核心原理、关键操作实现和实际使用场景。队列作为基础数据结构,在缓存机制、任务调度、消息队列等场景中有着广泛应用,掌握数组队列的实现,是深入学习更复杂数据结构(如优先级队列)的重要基础。