队列
# 队列 (Queue) 基本概念
队列(Queue)是一种常见的线性数据结构,遵循先进先出(First-In-First-Out, FIFO)的原则。类似于我们在现实生活中排队等待的场景,先来的人先被服务。
在队列中,元素的插入操作(入队)是在队列尾部进行,而元素的删除操作(出队)是在队列头部进行。这使得队列成为一种适合于顺序处理任务的数据结构。
队列通常具有以下两个基本操作:
- 入队(Enqueue): 将元素添加到队列尾部。
- 出队(Dequeue): 从队列头部移除一个元素。
除了基本的入队和出队操作,队列还具有以下重要概念:
- 队列头部(Front): 指向队列中第一个元素的指针或引用。
- 队列尾部(Back): 指向队列中最后一个元素的指针或引用。
- 空队列(Empty Queue): 不包含任何元素的队列。
- 满队列(Full Queue): 当队列达到其最大容量时,无法再插入新的元素。
队列可以使用数组或链表等数据结构来实现。在 C++ 标准库中,我们可以使用 std::queue
模板类来实现队列,它默认使用 std::deque
作为底层容器。
需要注意的是,队列是一种单向的数据结构,只能从队列尾部插入元素,从队列头部删除元素。如果需要在队列中间位置进行操作,可能需要转换为其他数据结构或使用额外的辅助数据结构。
队列在算法、操作系统、网络通信等领域中都有广泛的应用。它有助于实现各种基于顺序处理的问题和任务。
队列中只有头部和尾部的元素才可以被外界使用,因此队列不允许有遍历行为。
尽管技术上存在可以遍历队列中的元素的方法,但这种操作违背了队列的设计初衷。如果你频繁需要访问队列中的所有元素,建议重新考虑数据结构的选择,比如使用链表或其他容器。
# 队列 (Queue) 函数接口
当使用队列(std::queue
)时,以下是一些重要的详细信息和注意事项:
# 包含头文件
要使用 std::queue
,需要包含 <queue>
头文件。
#include <queue>
# 队列的创建
可以通过下面的方式声明一个队列:
std::queue<int> q;
在上述示例中,int
是队列中元素的类型,可以根据需要替换为其他类型。
# 元素插入
可以使用 push
方法将元素插入队列尾部。
q.push(42);
上述示例将整数 42 插入了队列尾部。
# 元素访问
可以使用 front
方法访问队列头部元素的值。
std::cout << q.front(); // 输出队列头部元素的值(不删除)
注意,front
方法不会从队列中删除头部元素,只是返回头部元素的值。
# 元素删除
可以使用 pop
方法从队列中删除队列头部元素。
q.pop();
上述示例将队列头部元素从队列中删除。
# 队列的大小
可以使用 size
方法获取队列内元素的数量。
std::cout << q.size(); // 输出队列中元素的个数
# 队列的判空
可以使用 empty
方法判断队列是否为空。
if (q.empty()) {
// 队列为空
} else {
// 队列不为空
}
empty
方法在队列为空时返回 true
,否则返回 false
。
# 队列函数接口表格
- 构造函数和析构函数
函数 | 描述 |
---|---|
queue() | 默认构造函数,创建一个空的队列 |
queue(const queue& other) | 复制构造函数,创建一个新的队列并复制另一个队列的内容 |
~queue() | 析构函数,销毁队列 |
- 运算符重载
运算符 | 描述 |
---|---|
operator= | 赋值运算符,将一个队列的内容赋值给另一个队列 |
operator== | 比较运算符,判断两个队列是否相等 |
operator!= | 比较运算符,判断两个队列是否不相等 |
- 成员函数
成员函数 | 描述 |
---|---|
push(value_type& value) | 将元素插入队列尾部 |
pop() | 删除队列头部元素 |
front() | 返回队列头部元素的引用(不删除) |
back() | 返回队列尾部元素的引用(不删除) |
size() | 返回队列中元素的数量 |
empty() | 判断队列是否为空 |
swap(queue& other) | 交换两个队列的内容 |
在上述表格中,value_type
是队列中元素的类型。请注意,队列类 std::queue
是基于其他容器实现的,默认情况下使用 std::deque
作为底层容器。可以使用其他容器,如 std::list
或 std::vector
,作为底层容器来实现队列。
# 基本操作程序示例
#include <iostream>
#include <queue>
// 使用全局命名空间 std
using namespace std;
int main() {
// 创建一个队列,存储 int 类型的元素
queue<int> q;
// 检查队列是否为空
if (q.empty()) {
cout << "队列当前为空" << endl;
}
// 向队列中插入元素
cout << "将 10, 20, 30 插入队列尾部" << endl;
q.push(10);
q.push(20);
q.push(30);
// 显示队列的大小
cout << "队列中元素的个数: " << q.size() << endl;
// 访问队列头部元素
cout << "队列头部元素的值: " << q.front() << endl;
// 删除队列头部元素
cout << "删除队列头部元素" << endl;
q.pop();
// 再次访问队列头部元素
cout << "现在队列头部元素的值: " << q.front() << endl;
// 显示队列的大小
cout << "队列中元素的个数: " << q.size() << endl;
// 继续删除队列中的所有元素
while (!q.empty()) {
cout << "删除队列头部元素: " << q.front() << endl;
q.pop();
}
// 最后再次检查队列是否为空
if (q.empty()) {
cout << "队列现在为空" << endl;
}
return 0;
}
# 解释:
- 创建队列:使用
std::queue<int> q;
创建一个存储int
类型元素的队列。 - 检查是否为空:使用
empty()
函数判断队列是否为空,并输出相应的提示信息。 - 插入元素:使用
push()
函数将元素 10, 20 和 30 插入队列中。 - 显示队列的大小:使用
size()
函数获取队列中元素的个数并输出。 - 访问队列头部元素:使用
front()
函数获取队列头部元素的值并输出。 - 删除队列头部元素:使用
pop()
函数删除队列头部元素,并再次访问新的队列头部元素。 - 清空队列:使用
while
循环和pop()
函数删除所有元素,直至队列为空。 - 再次检查是否为空:最后再次使用
empty()
函数判断队列是否为空,并输出相应的提示信息。
# 优先队列 (Priority Queue) 基本概念
优先队列(Priority Queue)是一种特殊的队列数据结构,每个元素都有一个优先级,元素根据优先级顺序出队。通常使用堆(Heap)来实现。
如图所示:我们通过使用push()
函数插入了元素,并且插入操作与普通队列相同。但是,当我们使用pop()
函数从队列中删除元素时,优先级最高的元素将首先被删除。
优先队列通常具有以下两个基本操作:
- 入队(Push/Enqueue): 将元素按优先级插入队列。
- 出队(Pop/Dequeue): 移除优先级最高的元素。
除了基本的入队和出队操作,优先队列还具有以下重要概念:
- 优先级(Priority): 元素的优先级决定了其在队列中的位置。
- 队列头部(Top): 指向优先级最高的元素的指针或引用。
优先队列在任务调度、路径规划等领域有广泛的应用。
# 优先队列 (Priority Queue) 函数接口
当使用优先队列(std::priority_queue
)时,以下是一些重要的详细信息和注意事项:
# 包含头文件
要使用 std::priority_queue
,需要包含 <queue>
头文件。
#include <queue>
# 优先队列的创建
可以通过下面的方式声明一个优先队列:
std::priority_queue<int> pq;
在上述示例中,int
是优先队列中元素的类型,可以根据需要替换为其他类型。
# 元素插入
可以使用 push
方法将元素按优先级插入优先队列。
pq.push(42);
上述示例将整数 42 插入优先队列。
# 元素访问
可以使用 top
方法访问优先队列头部元素的值。
std::cout << pq.top(); // 输出优先队列头部元素的值(不删除)
注意,top
方法不会从优先队列中删除头部元素,只是返回头部元素的值。
# 元素删除
可以使用 pop
方法从优先队列中删除优先队列头部元素。
pq.pop();
上述示例将优先队列头部元素从优先队列中删除。
# 优先队列的大小
可以使用 size
方法获取优先队列内元素的数量。
std::cout << pq.size(); // 输出优先队列中元素的个数
# 优先队列的判空
可以使用 empty
方法判断优先队列是否为空。
if (pq.empty()) {
// 优先队列为空
} else {
// 优先队列不为空
}
empty
方法在优先队列为空时返回 true
,否则返回 false
。
# 优先队列函数接口表格
- 构造函数和析构函数
函数 | 描述 |
---|---|
priority_queue() | 默认构造函数,创建一个空的优先队列 |
priority_queue(const priority_queue& other) | 复制构造函数,创建一个新的优先队列并复制另一个优先队列的内容 |
~priority_queue() | 析构函数,销毁优先队列 |
- 运算符重载
运算符 | 描述 |
---|---|
operator= | 赋值运算符,将一个优先队列的内容赋值给另一个优先队列 |
operator== | 比较运算符,判断两个优先队列是否相等 |
operator!= | 比较运算符,判断两个优先队列是否不相等 |
- 成员函数
成员函数 | 描述 |
---|---|
push(value_type& value) | 将元素按优先级插入优先队列 |
pop() | 删除优先队列头部元素 |
top() | 返回优先队列头部元素的引用(不删除) |
size() | 返回优先队列中元素的数量 |
empty() | 判断优先队列是否为空 |
swap(priority_queue& other) | 交换两个优先队列的内容 |
在上述表格中,value_type
是优先队列中元素的类型。优先队列类 std::priority_queue
使用最大堆作为底层实现,如果需要自定义优先级,可以使用自定义比较函数。
# 自定义比较函数
struct Compare {
bool operator()(const int& a, const int& b) {
// 自定义比较规则
return a > b; // 或其他规则
}
};
std::priority_queue<int, std::vector<int>, Compare> pq;
# 基本操作程序示例
#include <iostream>
#include <queue>
#include <vector>
// 自定义比较函数
struct Compare {
bool operator()(const int& a, const int& b) {
return a > b; // 这里是最小堆
}
};
// 使用全局命名空间 std
using namespace std;
int main() {
// 创建一个优先队列,存储 int 类型的元素,使用自定义比较函数
priority_queue<int, vector<int>, Compare> pq;
// 检查优先队列是否为空
if (pq.empty()) {
cout << "优先队列当前为空" << endl;
}
// 向优先队列中插入元素
cout << "将 30, 10, 20 插入优先队列" << endl;
pq.push(30);
pq.push(10);
pq.push(20);
// 显示优先队列的大小
cout << "优先队列中元素的个数: " << pq.size() << endl;
// 访问优先队列头部元素
cout << "优先队列头部元素的值: " << pq.top() << endl;
// 删除优先队列头部元素
cout << "删除优先队列头部元素" << endl;
pq.pop();
// 再次访问优先队列头部元素
cout << "现在优先队列头部元素的值: " << pq.top() << endl;
// 显示优先队列的大小
cout << "优先队列中元素的个数: " << pq.size() << endl;
// 继续删除优先队列中的所有元素
while (!pq.empty()) {
cout << "删除优先队列头部元素: " << pq.top() << endl;
pq.pop();
}
// 最后再次检查优先队列是否为空
if (pq.empty()) {
cout << "优先队列现在为空" << endl;
}
return 0;
}
# 解释:
- 创建优先队列:使用
std::priority_queue<int, std::vector<int>, Compare> pq;
创建一个存储int
类型元素并使用自定义比较函数的优先队列。 - 检查是否为空:使用
empty()
函数判断优先队列是否为空,并输出相应的提示信息。 - 插入元素:使用
push()
函数将元素 30, 10 和 20 插入优先队列中。 - 显示优先队列的大小:使用
size()
函数获取优先队列中元素的个数并输出。 - 访问优先队列头部元素:使用
top()
函数获取优先队列头部元素的值并输出。 - 删除优先队列头部元素:使用
pop()
函数删除优先队列头部元素,并再次访问新的优先队列头部元素。 - 清空优先队列:使用
while
循环和pop()
函数删除所有元素,直至优先队列为空。 - 再次检查是否为空:最后再次使用
empty()
函数判断优先队列是否为空,并输出相应的提示信息。