priority_queue使用

本文探讨了`priority_queue`的本质,它是一个容器适配器,依赖于algorithm库中的堆操作。默认使用`vector`作为内部容器并采用`std::less`作为比较函数。文章还介绍了`priority_queue`的初始化和常规使用方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

priority_queue分析

priority_queue是容器适配器,并不是容器。其并没有单独实现任何容器相关功能,而是在现有容器的基础上进行了再封装而已。
参照如下源代码我们不难看出,其实现依靠了algorithm库相关与heap的操作

	// stl_queue.h   push方法
      void
      push(value_type&& __x)
      {
	c.push_back(std::move(__x));
	std::push_heap(c.begin(), c.end(), comp);
      }

在源码中我们还能发现,其包含如下定义

  template<typename _Tp, typename _Sequence = vector<_Tp>,
	   typename _Compare  = less<typename _Sequence::value_type> >
    class priority_queue
    {
    ....
protected:
      //  See queue::c for notes on these names.
      _Sequence  c;
      _Compare   comp;
      }
    ....

从中可以看出,其默认使用vector<>作为其内部存储数据的容器,而传递的函数默认使用std::less<>类型。
让我们接着看一下std::less的定义,可以看出其就是一个结构体,定义了operator(),因此可以作为函数对象进行传递。而其底层实现仅是调用了类型变量之间的operator<。

  template<typename _Tp>
    struct less : public binary_function<_Tp, _Tp, bool>
    {
      _GLIBCXX14_CONSTEXPR
      bool
      operator()(const _Tp& __x, const _Tp& __y) const
      { return __x < __y; }
    };

使用方法

  • 初始化
void priorityQueueInitialization() {

    /* 
    * 模板原型 
    * template<
    *   class T,
    *   class Container = std::vector<T>,
    *   class Compare = std::less<typename Container::value_type>
    * > class priority_queue; 
    * 
    * T : 操作的数据类型
    * Container: 使用的容器
    * Compare:   函数对象的类型(class, 函数指针, Lambda表达式),其必须满足Compare要求
    * 
    * 对于Compare,个人感觉是一个历史遗留问题,function之后我们明显可以在构造的时候不传入这个参数。
    */

    // 使用简单类型
    std::vector<int> vec {1, 2, 3, 4, 5, 6};
    std::vector<int> vv{vec.begin(), vec.end()};
    std::priority_queue<int> q1();                           // default construct
    std::priority_queue<int> q2(std::greater<int>);          // 初始化compare 函数
    std::priority_queue<int> q3(std::less<int>(), vec);      // 使用vec的内容初始化priority队列

    std::priority_queue<int> q4(vec.begin(), vec.end());     
    std::priority_queue<int, std::vector<int>, std::greater<int>> q5(vec.begin(), vec.end(), std::greater<int>(), vv);
}
  • 常规使用方法
bool operator<(const std::pair<size_t, std::string>& lhs, const std::pair<size_t, std::string>& rhs) {
    return lhs.first > rhs.first;
}


// 利用全特化,我们特化less模板来达到目的
namespace std{

template<>
struct less<std::pair<size_t, std::string>> 
{
    bool operator()(const std::pair<size_t, std::string>& lhs, const std::pair<size_t, std::string>& rhs) {
        return lhs.first > rhs.first;
    };
};

}



void priorityQueueUsageMethod() {

    using priorityThreadPair = std::pair<size_t, std::string>;      // thread_priority 、name
    auto priorityThreadPairComp1 = [](const priorityThreadPair &lhs, const priorityThreadPair &rhs) ->bool {
                                        return lhs.first > rhs.first;
                                    };

    struct PriorityThreadPairComp2 {
        bool operator() (const priorityThreadPair &lhs, const priorityThreadPair &rhs) {
            return lhs.first > rhs.first;
        }
    }priorityThreadPairComp2;

    std::priority_queue<priorityThreadPair, std::vector<priorityThreadPair>, decltype(priorityThreadPairComp1)> q1(priorityThreadPairComp1);
    
    // 这里也可以传递函数对象,只要其支持函数操作
    std::priority_queue<priorityThreadPair, std::vector<priorityThreadPair>, PriorityThreadPairComp2> q1(priorityThreadPairComp2);

    /*
     * 这里相当于 std::priority_queue<priorityThreadPair, std::vector<priorityThreadPair>, std::less<priorityThreadPair>> q1;
     * 其中less的源代码如下:
                template<typename _Tp>
                struct less : public binary_function<_Tp, _Tp, bool>
                {
                _GLIBCXX14_CONSTEXPR
                bool
                operator()(const _Tp& __x, const _Tp& __y) const
                { return __x < __y; }
                };
        发现起始就是相当于调用了operator < ,所以我们可以直接重载这个操作符。
    */

    /*
     * 我们还可以利用全特化的方式来达到目的
    */
    std::priority_queue<priorityThreadPair> q1;


    q1.push({12, "t1"});
    q1.push({100, "t2"});
    q1.push({25, "t3"});
    while(!q1.empty()) {
        const auto& p = q1.top();
        std::cout << p.first << "   " << p.second << std::endl;
        q1.pop();
    }    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值