队列是遵循先进先出原则的典型线性数据结构,核心操作包括入队、出队、查看队首元素、判断队列是否为空等,在任务调度、缓冲区管理等场景中应用广泛。C++中既可以使用标准库提供的std::queue容器适配器快速实现队列功能,也可以通过自定义链表手动实现队列的完整逻辑。
std::queue的基本使用
std::queue是C++标准库中的容器适配器,底层默认使用std::deque作为容器,也可以指定其他符合要求的底层容器,比如std::list。它封装了队列的核心操作,使用起来非常简单,不需要开发者手动处理内存管理问题。
std::queue核心操作
- push(const T& val):将元素val加入队列尾部,即入队操作
- pop():移除队列头部的元素,即出队操作,该函数无返回值
- front():返回队列头部元素的引用,不会移除元素
- back():返回队列尾部元素的引用
- empty():判断队列是否为空,为空返回true,否则返回false
- size():返回队列中元素的个数
std::queue使用示例
下面的代码演示了使用std::queue实现整型队列的基本操作:
#include <iostream>
#include <queue>
int main() {
// 创建int类型的队列
std::queue<int> q;
// 入队操作
q.push(10);
q.push(20);
q.push(30);
// 查看队首和队尾元素
std::cout << "队首元素: " << q.front() << std::endl;
std::cout << "队尾元素: " << q.back() << std::endl;
// 出队操作
q.pop();
std::cout << "出队后队首元素: " << q.front() << std::endl;
// 判断队列是否为空并输出元素个数
std::cout << "队列是否为空: " << (q.empty() ? "是" : "否") << std::endl;
std::cout << "队列元素个数: " << q.size() << std::endl;
return 0;
}
用链表手动实现队列
如果需要更灵活地控制队列的实现逻辑,或者在一些不允许使用标准库的场景下,可以通过自定义链表来实现队列。链表实现的队列不需要预先分配固定大小的存储空间,插入和删除操作的时间复杂度都是O(1)。
链表队列的结构设计
链表实现的队列需要维护两个指针,分别指向链表的头部(队首)和尾部(队尾),还需要记录队列的元素个数。节点结构包含存储的数据和指向下一个节点的指针。
链表队列的实现代码
下面是完整的链表队列实现,包含入队、出队、查看队首、判空、获取大小等核心功能:
#include <iostream>
// 队列节点结构
template <typename T>
struct QueueNode {
T data; // 节点存储的数据
QueueNode<T>* next; // 指向下一个节点的指针
QueueNode(const T& val) : data(val), next(nullptr) {}
};
// 链表实现的队列类
template <typename T>
class LinkedQueue {
private:
QueueNode<T>* front_ptr; // 队首指针
QueueNode<T>* rear_ptr; // 队尾指针
int queue_size; // 队列元素个数
public:
// 构造函数,初始化空队列
LinkedQueue() : front_ptr(nullptr), rear_ptr(nullptr), queue_size(0) {}
// 析构函数,释放所有节点内存
~LinkedQueue() {
while (!empty()) {
pop();
}
}
// 入队操作,将元素添加到队尾
void push(const T& val) {
QueueNode<T>* new_node = new QueueNode<T>(val);
if (empty()) {
// 队列为空时,队首和队尾都指向新节点
front_ptr = rear_ptr = new_node;
} else {
// 队列不为空时,将新节点链接到队尾
rear_ptr->next = new_node;
rear_ptr = new_node;
}
queue_size++;
}
// 出队操作,移除队首元素
void pop() {
if (empty()) {
std::cout << "队列为空,无法出队" << std::endl;
return;
}
QueueNode<T>* temp = front_ptr;
front_ptr = front_ptr->next;
delete temp;
queue_size--;
// 如果出队后队列为空,更新队尾指针为nullptr
if (front_ptr == nullptr) {
rear_ptr = nullptr;
}
}
// 获取队首元素
T& front() {
if (empty()) {
throw std::runtime_error("队列为空,无队首元素");
}
return front_ptr->data;
}
// 获取队首元素的const版本
const T& front() const {
if (empty()) {
throw std::runtime_error("队列为空,无队首元素");
}
return front_ptr->data;
}
// 判断队列是否为空
bool empty() const {
return queue_size == 0;
}
// 获取队列元素个数
int size() const {
return queue_size;
}
};
int main() {
// 测试链表队列
LinkedQueue<int> q;
q.push(100);
q.push(200);
q.push(300);
std::cout << "队首元素: " << q.front() << std::endl;
std::cout << "队列大小: " << q.size() << std::endl;
q.pop();
std::cout << "出队后队首元素: " << q.front() << std::endl;
std::cout << "队列是否为空: " << (q.empty() ? "是" : "否") << std::endl;
return 0;
}
两种实现方式的对比
std::queue和链表实现的队列各有适用场景,具体差异如下:
| 对比维度 | std::queue | 链表实现队列 |
|---|---|---|
| 实现复杂度 | 极低,直接调用接口即可 | 较高,需要手动实现节点和指针逻辑 |
| 内存管理 | 自动管理,无需手动释放 | 需要手动处理节点内存,避免内存泄漏 |
| 灵活性 | 底层容器可配置,但功能被封装 | 可完全自定义逻辑,灵活性更高 |
| 适用场景 | 常规业务开发,快速实现队列功能 | 底层开发、需要自定义队列逻辑的场景 |
如果是常规的业务开发,优先选择std::queue,减少重复开发工作;如果需要在队列中增加特殊功能,或者运行环境不支持标准库,再考虑用链表手动实现队列。
C++std::queue链表队列实现修改时间:2026-06-22 12:28:07