• priority_queue学习


    转自:https://blog.csdn.net/weixin_36888577/article/details/79937886

    2.函数原型

    priority_queue<Type, Container, Functional>

     Type 就是数据类型,Container 就是容器类型(默认使用的是vector),Functional 就是比较的方式,默认是大顶堆。

    //降序队列(默认)
    priority_queue <int,vector<int>,less<int> >q;

    //
    升序队列 priority_queue <int,vector<int>,greater<int> > q;//这里没有空格也是对的

    2.1为什么less是大顶堆?

    https://blog.csdn.net/caozicheng1999/article/details/109907795

    greater和less都是结构体,分别都重载了()运算符:

    // TEMPLATE STRUCT greater
    template<class _Ty>
        struct greater
            : public binary_function<_Ty, _Ty, bool>
        {    // functor for operator>
        bool operator()(const _Ty& _Left, const _Ty& _Right) const
            {    // apply operator> to operands
            return (_Left > _Right);//是大于
            }
        };
     
    // TEMPLATE STRUCT less
    template<class _Ty>
        struct less
            : public binary_function<_Ty, _Ty, bool>
        {    // functor for operator<
        bool operator()(const _Ty& _Left, const _Ty& _Right) const
            {    // apply operator< to operands
            return (_Left < _Right);//是小于
            }
        };

     在sort中,默认的是less<>(),从小到大排序;greater<>()是从大到小排序。

     在优先级队列中,当使用默认的定义时,即less<>(),当向堆中插入一个元素时,直接插入在了尾部,然后向上调整:

    void push(const value_type& _Val) {
        c.push_back(_Val);
        _STD push_heap(c.begin(), c.end(), comp);
    }

    通过_Push_heap_by_index

    template <class _RanIt, class _Ty, class _Pr>
    _CONSTEXPR20 void _Push_heap_by_index(
        _RanIt _First, _Iter_diff_t<_RanIt> _Hole, _Iter_diff_t<_RanIt> _Top, _Ty&& _Val, _Pr _Pred) {
        // percolate _Hole to _Top or where _Val belongs, using _Pred
        using _Diff = _Iter_diff_t<_RanIt>;
        for (_Diff _Idx = (_Hole - 1) >> 1; // shift for codegen  //这里定义的_Idx应该就是父节点的下标
             _Top < _Hole && _DEBUG_LT_PRED(_Pred, *(_First + _Idx), _Val); //当
             _Idx = (_Hole - 1) >> 1) { // shift for codegen
            // move _Hole up to parent
            *(_First + _Hole) = _STD move(*(_First + _Idx));
            _Hole             = _Idx;
        }
    
        *(_First + _Hole) = _STD move(_Val); // drop _Val into final hole
    }

     关键是这一句, _DEBUG_LT_PRED(_Pred, *(_First + _Idx), _Val),传入的仿函数用在了这里,当 *(_First + _Idx) < _Val 时返回 true ,即当父节点的值小于新插入的值时继续调整,less函数返回true,父节点被插入结点换了下去,所以我们才可以得出结论 less函数,返回true时,左边的优先级低于右边的优先级,也就清楚了为什么默认传入less反而形成的是大根堆。

    优先级队列中less也就是<定义的是优先级,针对a<b返回true,表示值小的那么优先级也低,因为b更大,所以b的优先级高,优先级队列是按照优先级排序的;

    针对greater,也就是重定义了>,a>b时返回true,值小的优先级反而高,所以是小顶堆。

    //确实挺难理解的。

    3.例子

    3.1普通用法

    #include <iostream>
    #include<vector>
    #include<queue>
    using namespace std;
    
    int main(){
        priority_queue<int> a;
        priority_queue<int, vector<int>, greater<int>> b;
        for(int i=0;i<5;i++)
            b.push(i);
        while(!b.empty()){
            cout<<b.top()<<" ";
            b.pop();
        }
    }
    #输出:
    0 1 2 3 4 

    注意,优先队列不能用for循环访问:

    for(auto bb:b)
        cout<<bb<<" ";
    
    //报错:
    'const class std::priority_queue<int,std::vector<int, 
    std::allocator<int> >, std::greater<int> >' has no member named 'end'

    就像队列不能通过for循环访问一样。

    3.2 pair比较

    #include <iostream>
    #include<vector>
    #include<queue>
    using namespace std;
    
    int main(){
        priority_queue<pair<int,int>> pq;
        pq.push(make_pair(3,5));//make_pair()是函数。
        pq.push(make_pair(4,6));
        pq.push(make_pair(1,7));
        while(!pq.empty()){
            cout<<pq.top().first<<" "<<pq.top().second<<endl;
            pq.pop();
        }
        return 0;
    }

    输出:

    4 6
    3 5
    1 7

    默认是大顶堆,默认的话就是less?但是是如何实现排序的呢?从小到大?然后每次top都是最后一个元素出来?

    3.3 自定义类型

    例子347. 前 K 个高频元素,需要定义一个小顶堆,

    static bool cmp(pair<int,int> a,pair<int,int> b){
            return a.second>b.second; //这里是>号
        }
    
    priority_queue<pair<int,int>,vector<pair<int,int>>,decltype(&cmp)> pq(cmp);   

     其中priority_queue的模板有三个参数:

    • 第一个是元素类型
    • 第二个是容器类型
    • 第三个是Compare,是size_type类型的,无符号整型。

    priority_queue的构造函数的参数中有comp,表示用于排序堆的比较对象。默认是less<T>大顶堆。如果是自定义的比较函数,那么需要向如上声明。

    当要自定义比较函数时,大于小于号的确定:

    template<class T>
    struct greater: public binary function<T, T, bool>
    {
        bool operator()(const T& x, const T& y) const
        {    
            return x > y;
        }
    };

     上面是greater类的模板,用它定义的优先队列是小顶堆。

    (即大于号定义小顶堆,默认是大顶堆,小于号定义大顶堆。)

  • 相关阅读:
    在SQL SERVER 2005中还原数据库时出现错误:system.data.sqlclient.sqlerror 媒体集有 2 个媒体簇 但只提供了 1 个。必须提供所有成员。 (microsoft.sqlserver.smo)
    Mysql的Root密码忘记,查看或修改的解决方法
    Win7系统如何设置FTP详细过程
    该设备或资源(127.0.0.1)未设置为接受端口“16823”上的连接。
    window7防火墙无法更改某些设置,错误代码0×80070422
    访问FTP站点下载文件,提示“当前的安全设置不允许从该位置下载文件”的解决方案
    解决SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT'OpenRowset/OpenDatasource' 的访问的方法
    按状态选择链接元素
    类选择器与ID选择器的比较
    关于创建Web图像时应记住的五个要素
  • 原文地址:https://www.cnblogs.com/BlueBlueSea/p/13870441.html
Copyright © 2020-2023  润新知