priority_queue

priority_queue 是 C++ 标准库中的一个容器适配器,定义在头文件 <queue> 中。它提供了一种优先队列的数据结构,类似于堆,能够根据元素的优先级来组织数据。默认情况下,它是一个最大堆,即最大的元素总是位于队首。你可以通过自定义比较函数实现最小堆。

一.特性

最大堆:默认情况下,priority_queue 是最大堆,队首元素是最大值。
动态大小:可以动态调整队列大小。
不支持随机访问:不像 vectordeque,你无法通过索引访问 priority_queue 中的元素。

二.模板定义

template <class T, class Container = std::vector<T>, class Compare = std::less<typename Container::value_type>>
class priority_queue;

T:存储的元素类型。
Container:用于存储元素的底层容器,默认是 std::vector
Compare:比较函数对象,默认是 std::less<T>,实现最大堆。

三.用法示例

1.基本用法

#include <iostream>
#include <queue>
#include <vector>

int main() {
    std::priority_queue<int> pq;
    pq.push(10);
    pq.push(5);
    pq.push(20);
    // 输出队首元素(最大值):20
    std::cout << "Top element: " << pq.top() << std::endl;
    pq.pop();  // 移除队首元素
    // 输出新的队首元素(剩余最大值):10
    std::cout << "New top element: " << pq.top() << std::endl;
    return 0;

}

2.最小堆的实现
可以通过自定义比较器来构造最小堆,将 std::greater<T> 作为第三个模板参数,或者使用负值来实现最小堆。

#include <iostream>
#include <queue>
#include <vector>

int main() {
    // 使用 std::greater<int> 创建最小堆
    std::priority_queue<int, std::vector<int>, std::greater<int>> min_pq;
    min_pq.push(10);
    min_pq.push(5);
    min_pq.push(20);
    // 输出最小值:5
    std::cout << "Top element (min): " << min_pq.top() << std::endl;
    return 0;
}

3.自定义类型的优先队列
你可以自定义比较器来处理复杂类型,如 structclass

#include <iostream>
#include <queue>
#include <vector>

struct Task {
    int priority;
    std::string name;
    // 自定义比较器,按优先级比较
    bool operator<(const Task& other) const {
        return priority < other.priority; 
    }
};

int main() {
    std::priority_queue<Task> task_pq;
    task_pq.push({3, "Task C"});
    task_pq.push({1, "Task A"});
    task_pq.push({2, "Task B"});
    // 输出优先级最高的任务
    std::cout << "Top task: " << task_pq.top().name << std::endl;  // 输出: Task C
    return 0;

}

四.常用成员函数

1.push()
向优先队列中添加一个元素。

   pq.push(30);

2.pop()
移除队首元素(优先级最高的元素)。注意,这不会返回该元素的值,所以需要在调用 pop() 之前先使用 top() 来获取队首元素。

   pq.pop();

3.top()
返回优先队列中的队首元素,即优先级最高的元素,但不移除它。

   int highest = pq.top();

4.empty()
检查优先队列是否为空,返回 true 表示为空,false 表示不为空。

   if (pq.empty()) {
       // 队列为空
   }

5.size()
返回优先队列中的元素个数。

   std::cout << "Size: " << pq.size() << std::endl;

Pair

pair 是 C++ 标准库中的一个模板类,定义在头文件<utility> 中。它用于存储一对值,可以是不同类型的值,提供了方便的方式来关联两个数据元素。

一.特性

  • pair 是一个模板类,可以容纳两个类型不同的值。
  • 两个值可以直接通过 first 和 second 成员变量来访问。
  • 常用于将两个相关联的值打包在一起传递或存储,像是键值对。

二.模板定义

template <class T1, class T2>  
struct pair {
    T1 first;
    T2 second;
};
  • T1:第一个元素的类型。
  • T2:第二个元素的类型。

二.创建 pair

1.直接初始化

std::pair<int, std::string> p(1, "apple");  

该语句创建了一个 pair,其中 first 为整数 1,second 为字符串 “apple”。

2.使用 make_pair 函数

auto p = std::make_pair(1, "apple");  

make_pair 函数可以自动推断类型,不需要显式指定模板参数。

三.用法示例

1.基本示例

#include <iostream>  
#include <utility>  // for std::pair and std::make_pair

int main() {   
// 创建 pair 并直接初始化   
std::pair<int, std::string> p(1, "apple");

// 使用 make_pair 创建 pair   
auto p2 = std::make_pair(2, "banana");

// 访问 first 和 second
    std::cout << "Pair 1: " << p.first << ", " << p.second << std::endl;
    std::cout << "Pair 2: " << p2.first << ", " << p2.second << std::endl;

return 0;
}

2.结合 map 使用
pair 常用于关联数据结构,例如 std::map,其元素通常是键值对的形式(即 pair)。

#include <iostream>  
#include <map>
#include <utility>

int main() {   
// 创建 map,map 的元素类型是 pair   
std::map<int, std::string> m;

// 插入元素,pair 类型的键值对
    m.insert(std::make_pair(1, "apple"));
    m.insert(std::pair<int, std::string>(2, "banana"));

// 访问 map 中的元素    for (const auto& entry : m) {
        std::cout << "Key: " << entry.first << ", Value: " << entry.second << std::endl;
    }

return 0;
}

三.常用成员

1.first 和 second
直接访问 pair 的第一个和第二个元素。

std::pair<int, double> p(10, 20.5);  
int key = p.first;   // 获取第一个元素
double value = p.second;  // 获取第二个元素

2.make_pair()
创建一个 pair 对象,函数会自动推断类型。

auto p = std::make_pair(5, "text");

3.operator==、operator!=
比较两个 pair 是否相等。

std::pair<int, int> p1(1, 2);  
std::pair<int, int> p2(1, 2);
if (p1 == p2) {
   std::cout << "Pairs are equal" << std::endl;
}

4.operator<、operator>
pair 可以按字典顺序比较:首先比较 first,如果 first 相等,则比较 second。

std::pair<int, int> p1(1, 2);  
std::pair<int, int> p2(1, 3);
if (p1 < p2) {
    std::cout << "p1 is smaller than p2" << std::endl;
}

Operator

比较函数应遵循严格弱排序规则,返回 true 表示第一个参数应该排在第二个参数之前。

bool operator()(int a, int b) const {  
    return a > b;  // 降序,最小堆
}

为什么这是降序?
这个比较函数会返回 true 当且仅当 a > b。也就是说,只有当 a 大于 b 时,a 会被排在 b 的前面。换句话说:

  • 如果 a = 5,b = 3,比较函数返回 true,表示 5 应该排在 3 之前。
  • 如果 a = 3,b = 5,比较函数返回 false,表示 3 应该排在 5 之后。

这与降序排列的逻辑一致:大的元素排在前面,小的元素排在后面。