在 C++ 中,队列(Queue)是一种遵循先进先出(First-In-First-Out,FIFO)原则的数据结构,即最先进入队列的元素会最先被移除。下面将从多个方面详细介绍如何实现和使用队列,包括使用标准库中的 std::queue
以及手动实现一个简单的队列。
下面分别介绍 C++ 标准库 std::queue
以及手动实现队列时常见的函数及其功能、使用示例和复杂度分析。
C++ 标准库 std::queue
中的函数
1. 构造函数
- 功能:用于创建
std::queue
对象。 - 示例:
#include <iostream>
#include <queue>
int main() {
// 默认构造函数,创建一个空的队列
std::queue<int> myQueue;
return 0;
}
2. empty()
- 功能:检查队列是否为空,若队列为空则返回
true
,否则返回false
。 - 复杂度: O ( 1 ) O(1) O(1)
- 示例:
#include <iostream>
#include <queue>
int main() {
std::queue<int> myQueue;
if (myQueue.empty()) {
std::cout << "队列为空" << std::endl;
}
return 0;
}
3. size()
- 功能:返回队列中元素的数量。
- 复杂度: O ( 1 ) O(1) O(1)
- 示例:
#include <iostream>
#include <queue>
int main() {
std::queue<int> myQueue;
myQueue.push(10);
myQueue.push(20);
std::cout << "队列的大小为: " << myQueue.size() << std::endl;
return 0;
}
4. front()
- 功能:返回队列中第一个(队首)元素的引用。若队列为空,调用此函数会导致未定义行为。
- 复杂度: O ( 1 ) O(1) O(1)
- 示例:
#include <iostream>
#include <queue>
int main() {
std::queue<int> myQueue;
myQueue.push(10);
std::cout << "队首元素是: " << myQueue.front() << std::endl;
return 0;
}
5. back()
- 功能:返回队列中最后一个(队尾)元素的引用。若队列为空,调用此函数会导致未定义行为。
- 复杂度: O ( 1 ) O(1) O(1)
- 示例:
#include <iostream>
#include <queue>
int main() {
std::queue<int> myQueue;
myQueue.push(10);
myQueue.push(20);
std::cout << "队尾元素是: " << myQueue.back() << std::endl;
return 0;
}
6. push()
- 功能:在队列的尾部插入一个新元素。
- 复杂度:平均 O ( 1 ) O(1) O(1)
- 示例:
#include <iostream>
#include <queue>
int main() {
std::queue<int> myQueue;
myQueue.push(10);
myQueue.push(20);
return 0;
}
7. pop()
- 功能:移除队列的第一个(队首)元素。若队列为空,调用此函数会导致未定义行为。
- 复杂度:平均 O ( 1 ) O(1) O(1)
- 示例:
#include <iostream>
#include <queue>
int main() {
std::queue<int> myQueue;
myQueue.push(10);
myQueue.pop();
if (myQueue.empty()) {
std::cout << "执行出队操作后,队列为空" << std::endl;
}
return 0;
}
1. 使用标准库中的 std::queue
1.1 简介
std::queue
是 C++ 标准库中的一个容器适配器,它基于其他容器(如 std::deque
或 std::list
)实现了队列的基本功能。使用 std::queue
可以方便快捷地实现队列操作,无需手动管理队列的底层数据结构。
1.2 常用操作及示例代码
#include <iostream>
#include <queue>
int main() {
// 创建一个存储整数的队列
std::queue<int> myQueue;
// 入队操作:使用 push() 方法将元素添加到队列尾部
myQueue.push(10);
myQueue.push(20);
myQueue.push(30);
// 检查队列是否为空:使用 empty() 方法
if (!myQueue.empty()) {
// 获取队列的大小:使用 size() 方法
std::cout << "队列的大小为: " << myQueue.size() << std::endl;
// 查看队首元素:使用 front() 方法
std::cout << "队首元素是: " << myQueue.front() << std::endl;
// 查看队尾元素:使用 back() 方法
std::cout << "队尾元素是: " << myQueue.back() << std::endl;
// 出队操作:使用 pop() 方法移除队首元素
myQueue.pop();
std::cout << "执行一次出队操作后,队首元素变为: " << myQueue.front() << std::endl;
}
return 0;
}
1.3 复杂度分析
- 入队操作
push()
:平均时间复杂度为 O ( 1 ) O(1) O(1)。 - 出队操作
pop()
:平均时间复杂度为 O ( 1 ) O(1) O(1)。 - 获取队首元素
front()
:时间复杂度为 O ( 1 ) O(1) O(1)。 - 获取队尾元素
back()
:时间复杂度为 O ( 1 ) O(1) O(1)。 - 检查队列是否为空
empty()
:时间复杂度为 O ( 1 ) O(1) O(1)。 - 获取队列大小
size()
:时间复杂度为 O ( 1 ) O(1) O(1)。
2. 手动实现一个简单的队列
2.1 实现思路
手动实现队列可以使用数组或链表作为底层数据结构。这里我们使用数组来实现一个固定大小的队列,通过两个指针 front
和 rear
分别表示队首和队尾的位置。
2.2 代码实现
#include <iostream>
#include <stdexcept>
const int MAX_SIZE = 100;
template <typename T>
class Queue {
private:
T data[MAX_SIZE];
int front;
int rear;
int size;
public:
// 构造函数,初始化队列
Queue() : front(0), rear(0), size(0) {}
// 判断队列是否为空
bool empty() const {
return size == 0;
}
// 判断队列是否已满
bool full() const {
return size == MAX_SIZE;
}
// 入队操作
void push(const T& value) {
if (full()) {
throw std::overflow_error("队列已满,无法入队");
}
data[rear] = value;
rear = (rear + 1) % MAX_SIZE;
++size;
}
// 出队操作
void pop() {
if (empty()) {
throw std::underflow_error("队列为空,无法出队");
}
front = (front + 1) % MAX_SIZE;
--size;
}
// 获取队首元素
T& frontElement() {
if (empty()) {
throw std::underflow_error("队列为空,没有队首元素");
}
return data[front];
}
const T& frontElement() const {
if (empty()) {
throw std::underflow_error("队列为空,没有队首元素");
}
return data[front];
}
// 获取队列的大小
int getSize() const {
return size;
}
};
int main() {
Queue<int> myQueue;
try {
// 入队操作
myQueue.push(10);
myQueue.push(20);
myQueue.push(30);
// 输出队列大小
std::cout << "队列大小: " << myQueue.getSize() << std::endl;
// 输出队首元素
std::cout << "队首元素: " << myQueue.frontElement() << std::endl;
// 出队操作
myQueue.pop();
std::cout << "执行一次出队操作后,队首元素变为: " << myQueue.frontElement() << std::endl;
} catch (const std::exception& e) {
std::cerr << "异常: " << e.what() << std::endl;
}
return 0;
}
2.3 复杂度分析
- 入队操作
push()
:时间复杂度为 O ( 1 ) O(1) O(1),因为只需要进行常数级的操作。 - 出队操作
pop()
:时间复杂度为 O ( 1 ) O(1) O(1),因为只需要更新队首指针。 - 获取队首元素
frontElement()
:时间复杂度为 O ( 1 ) O(1) O(1),因为可以直接访问队首元素。 - 判断队列是否为空
empty()
:时间复杂度为 O ( 1 ) O(1) O(1),因为只需要比较队列的大小。 - 判断队列是否已满
full()
:时间复杂度为 O ( 1 ) O(1) O(1),因为只需要比较队列的大小。 - 获取队列大小
getSize()
:时间复杂度为 O ( 1 ) O(1) O(1),因为可以直接返回队列的大小。