C++开发必备之stl进阶(五 优先队列)

priority_queue(优先队列)

std::priority_queue 是 C++ 标准模板库 (STL) 中提供的优先队列容器。优先队列是一种特殊的队列数据结构,其中元素是按照优先级排序的,默认情况下优先队列是一个最大堆(即总是优先返回最大元素)。std::priority_queue 允许我们快速访问队列中优先级最高的元素。

1. 基本概念

std::priority_queue 是一种基于堆的数据结构,堆是一个完全二叉树,其中每个父节点的值都大于(或小于)其子节点的值。priority_queue 是最大堆,因此最大元素始终位于队列的顶部。

2. 优先队列的使用

std::priority_queue 是通过模板类定义的,模板参数包括:

  1. 类型:优先队列中元素的类型。
  2. 容器:用于存储元素的底层容器,默认为std::vector
  3. 比较函数:用于定义元素优先级的比较方式,默认是std::less<T>,表示最大堆。
    std::priority_queue<T, Container, Compare>
    

  • T:存储元素的类型。
  • Container:底层容器类型(通常为std::vector,也可以是std::deque等)。
  • Compare:比较方式,默认是std::less<T>,用于创建最大堆。如果希望创建最小堆,可以使用std::greater<T>

3. 常用操作

  • push():将元素插入到优先队列中。
  • pop():移除优先队列中优先级最高的元素(但不返回它的值)。
  • top():返回优先队列中优先级最高的元素。
  • empty():检查优先队列是否为空。
  • size():返回优先队列中元素的数量。

4. 示例代码

4.1 最大堆(默认行为)

默认情况下,std::priority_queue 是一个最大堆,这意味着top()函数返回当前优先队列中最大的元素。

#include <iostream>
#include <queue>

int main()
{
    // 默认是最大堆
    std::priority_queue<int> pq;

    pq.push(10);
    pq.push(30);
    pq.push(20);
    pq.push(5);

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

    // 输出最大元素并移除它
    while (!pq.empty()) 
    {
        std::cout << pq.top() << " ";  // 输出优先级最高的元素
        pq.pop();  // 移除优先级最高的元素
    }

    return 0;
}

输出

Priority queue size: 4
30 20 10 5 
4.2 最小堆

为了实现最小堆,需要使用std::greater<T>作为比较函数。可以在声明std::priority_queue时指定std::vector<int>作为容器,并使用std::greater<int>来表示最小堆。

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

int main()
{
    // 最小堆
    std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;

    minHeap.push(10);
    minHeap.push(30);
    minHeap.push(20);
    minHeap.push(5);

    std::cout << "Priority queue size: " << minHeap.size() << std::endl;

    // 输出最小元素并移除它
    while (!minHeap.empty()) 
    {
        std::cout << minHeap.top() << " ";  // 输出优先级最高的元素
        minHeap.pop();  // 移除优先级最高的元素
    }

    return 0;
}

 输出

Priority queue size: 4
5 10 20 30 
4.3 自定义对象的优先级队列

可以通过自定义比较函数来定义复杂类型的优先级队列。例如,假设我们有一个Person类,我们希望基于年龄创建一个优先队列:

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

struct Person
{
    std::string name;
    int age;

    Person(std::string name, int age) : name(name), age(age) {}
};

// 比较函数,按年龄升序排列
struct ComparePerson
{
    bool operator()(const Person& p1, const Person& p2)
    {
        return p1.age > p2.age;  // 年龄小的优先级高
    }
};

int main()
{
    // 使用自定义比较函数
    std::priority_queue<Person, std::vector<Person>, ComparePerson> pq;

    pq.push(Person("Alice", 30));
    pq.push(Person("Bob", 25));
    pq.push(Person("Charlie", 35));

    // 输出优先级最高的元素(年龄最小的)
    while (!pq.empty()) 
    {
        Person p = pq.top();
        std::cout << p.name << " (" << p.age << ")" << std::endl;
        pq.pop();
    }

    return 0;
}

输出

Bob (25)
Alice (30)
Charlie (35)
4.4 与STL算法结合

std::priority_queue可以与STL算法结合使用。例如,使用std::vector初始化优先队列,并直接插入一批元素。

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

int main()
{
    std::vector<int> vec = {10, 20, 30, 5};

    // 使用已有的数据构建优先队列
    std::priority_queue<int> pq(vec.begin(), vec.end());

    // 输出优先级最高的元素
    while (!pq.empty()) 
    {
        std::cout << pq.top() << " ";
        pq.pop();
    }

    return 0;
}

输出

30 20 10 5

5. 优先队列的复杂度

  • push() 操作的时间复杂度为 O(log n)
  • pop() 操作的时间复杂度为 O(log n)
  • top() 操作的时间复杂度为 O(1)

由于priority_queue是基于堆实现的,所以插入、删除的操作会重新调整堆结构,保持堆的有序性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值