优先级队列std::priority_queue

优先级队列std::priority_queue

刷Dijkstra算法预备知识。

C++ 优先级队列(std::priority_queue)详解

std::priority_queue 是 C++ 标准库中的一个容器适配器,它提供常数时间的最大(小)元素查找,对数时间的元素插入和删除。优先级队列通常使用堆(heap)数据结构实现,默认情况下是最大堆

基本定义与参数

std::priority_queue 的模板定义如下:

template<
    class T,                          // 元素类型
    class Container = std::vector<T>, // 底层容器类型
    class Compare = std::less<T>      // 比较函数类型
> class priority_queue;
  • T:存储的元素类型。
  • Container:底层容器,必须支持 front()push_back()pop_back() 等操作,默认是 std::vector<T>
  • Compare:比较函数,决定元素的优先级顺序。默认是 std::less<T>,即最大堆。
最大堆(默认行为)

最大堆的堆顶元素是队列中最大的元素。

    priority_queue<int> maxHeap;
    // 等价于:priority_queue<int, vector<int>, less<int>> maxHeap;
}

关键点

  • 比较函数 less<T>a < b 返回 true 时,b 的优先级更高。
  • 堆顶元素:始终是最大元素(top() 返回最大值)。
最小堆

最小堆的堆顶元素是队列中最小的元素。要实现最小堆,需显式指定 greater<T> 作为比较函数:

    // 创建最小堆
    priority_queue<int, vector<int>, greater<int>> minHeap;

关键点

  • 比较函数 greater<T>a > b 返回 true 时,b 的优先级更高。
  • 堆顶元素:始终是最小元素(top() 返回最小值)。
自定义比较函数

除了使用 less<T>greater<T>,还可以自定义比较函数。

  1. 函数对象(Functor)
struct Compare {
    bool operator()(const int& a, const int& b) const {
        return a < b; // 最大堆
        // return a > b; // 最小堆
    }
};

priority_queue<int, vector<int>, Compare> heap;
  1. Lambda 表达式
auto cmp = [](const int& a, const int& b) {
    return a < b; // 最大堆
};

priority_queue<int, vector<int>, decltype(cmp)> heap(cmp);
  1. 自定义结构体重载运算符
// dijkstra算法中常用自定义节点
 struct State {
        int id;
        double distFromStart;

        State(int id, double distFromStart) : id(id), distFromStart(distFromStart) {}

        // 默认使用std::less<T>作为比较函数(最大堆),a<b则a优先级<b优先级,b在a前
        // 指定std::greater<T>则是最小堆,a>b则b优先级>a优先级,b在a前
        // 最大堆用<,最小堆用>,后面的优先级高
        // 这里最小堆但是使用逆序判定,使得大的优先级更高
        // bool operator>(const State& other) const {
        //     return distFromStart < other.distFromStart;
        // }
        bool operator<(const State& other) const {
            return distFromStart < other.distFromStart;
        }
    };
最大堆的逆序使用

使用less比较,但是返回a>b,等效最小堆:

	bool operator<(const State& other) const {
    	return distFromStart > other.distFromStart;
    }
    priority_queue<State, vector<State>, less<State>> pq;
    // 等效代码如下
    bool operator>(const State& other) const {
    	return distFromStart > other.distFromStart;
    }
    priority_queue<State, vector<State>, greater<State>> pq;
最小堆的逆序使用

使用greater比较,但是返回a<b,等效最大堆:

	bool operator>(const State& other) const {
    	return distFromStart < other.distFromStart;
    }
    priority_queue<State, vector<State>, greater<State>> pq;
    // 等效代码如下
    bool operator<(const State& other) const {
    	return distFromStart > other.distFromStart;
    }
    priority_queue<State, vector<State>, less<State>> pq;
总结
堆类型比较函数堆顶元素比较函数定义及堆定义
最大堆less<T>(默认)最大值return a<b; priority_queue<int, vector<int>, less<int>> maxHeap;
最小堆greater<T>最小值return a>b; priority_queue<int, vector<int>, greater<int>> minHeap;
逆序最大堆 (等效最小堆)less<T>最小值return a>b; priority_queue<int, vector<int>, less<int>> minHeap;
逆序最小堆(等效最大堆)greater<T>最大值return a<b; priority_queue<int, vector<int>, greater<int>> maxHeap;

通过灵活调整比较函数,可以让优先级队列适应各种需求,包括非标准的排序逻辑。
别用逆序了,有点绕,正常用就行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值