优先级队列

目录

介绍

仿函数

介绍 

示例

模拟实现

注意点

元素类型

代码

算法题示例

数组中第k个最大元素

题目

思路

代码


介绍

优先队列是一种容器适配器,默认它的第一个元素总是它所有元素中最大的
  • 类似于,可以随时插入元素,并且只能访问最大/小元素(优先队列中位于顶部的元素)
  • 优先级队列_第1张图片
  • 标准容器类vector和deque都能满足上面的接口需求(支持随机迭代器 -- 保持堆结构,支持头插头删)
  • 默认情况下,如果没有为它的实例化指定容器类,则默认是vector
  • 仿函数 -- 大堆传入less( 可以记成 降序),小堆传入greater(可以记成升序) 

仿函数

介绍 

在c++里,优先级队列模板有三个参数,第三个参数就是仿函数

仿函数(Functor)是一种重载了函数调用操作符( )的对象,使得对象能够像函数一样被调用, 并返回结果

仿函数是一种强大的工具,允许以一种更灵活的方式将 函数逻辑嵌入到对象 中,并且能够在算法和其他上下文中被使用

示例

以下是一个拿到较小数的类

优先级队列_第2张图片

使用前需要先实例化,调用的时候我们写的是 对象名(参数列表) ,但实际上语法是 对象名.operator() (参数列表)

优先级队列_第3张图片

优先级队列_第4张图片  

模拟实现

注意点

堆的向上调整和向下调整 的实现

仿函数的使用 -- 重载符号

元素类型(以下使用date作为示例)

  • 传入自定义类型的话,里面一定要重载比较符号,不然没法调用仿函数里的比较符号
  • 优先级队列_第5张图片
  • 传入参数如果是指针 -- 比较的就是地址的大小(因为类型是指针),而不是对象内容,所以需要再写一个比较方法
  • template 
    class LessPDate
    {
    public:
        bool operator()(const T *p1, const T *p2)
        {
            return *p1 < *p2;
        }
    };

改动前: (结果随机 -- 地址随机生成)

改动后:

代码

#include 
#include 
#include 
#include 
#include 

using namespace std;

namespace bit
{
    template 
    class myless
    {
    public:
        bool operator()(const T &a, const T &b)
        {
            return a < b;
        }
    };
    template 
    class mygreater
    {
    public:
        bool operator()(const T &a, const T &b)
        {
            return a > b;
        }
    };

    template , class Compare = myless> // 默认是大堆
    class mypriority_queue
    {
    private:
        void adjust_down(int parent)
        { // 大堆找大往上调,往下走
            int child = parent * 2 + 1;
            while (child < size())
            {
                if (child + 1 < size() && comp(c[child], c[child + 1]))
                {
                    child++;
                }
                if (comp(c[parent], c[child]))
                {
                    swap(c[parent], c[child]);
                    parent = child;
                    child = parent * 2 + 1;
                }
                else
                {
                    break;
                }
            }
        }
        void adjust_up(int child)
        {
            int parent = (child - 1) / 2;
            while (child > 0)
            {
                if (comp(c[parent], c[child]))
                {
                    swap(c[parent], c[child]);
                    child = parent;
                    parent = (child - 1) / 2;
                }
                else
                {
                    break;
                }
            }
        }

    public:
        mypriority_queue()
        {
        }

        template 
        mypriority_queue(InputIterator first, InputIterator last)
        {
            while (first != last)
            {
                c.push(*first);
                ++first;
            }
            for (size_t i = (size() - 1 - 1) / 2; i >= 0; --i)
            { // 建堆(光靠push的向上调整 不足以建立完善的堆结构)
                adjust_down(i);
            }
        }

        bool empty() const
        {
            return c.empty();
        }
        size_t size() const
        {
            return c.size();
        }
        T &top()
        {
            return c.front();
        }
        void push(const T &x)
        {
            c.push_back(x);
            adjust_up(size() - 1);
        }
        void pop()
        {
            swap(top(), c[size() - 1]);
            c.pop_back();
            adjust_down(0);
        }

    private:
        Container c;
        Compare comp;
    };
};

算法题示例

数组中第k个最大元素

题目

215. 数组中的第K个最大元素 - 力扣(LeetCode)

优先级队列_第6张图片

思路

很明显是栈的第k大问题

既可以建立大堆,出k-1个元素,拿到第k个

也可以建立k个元素的小堆,遍历完元素后,堆顶就是第k个

代码

int findKthLargest(vector& nums, int k) {
        // //大堆
        // priority_queue q(nums.begin(),nums.end());
        // while(--k){
        //     q.pop();
        // }
        // return q.top();

        //小堆
         priority_queue,greater> q(nums.begin(),nums.begin()+k);
         for(auto i=nums.begin()+k;i!=nums.end();++i){
             if(*i>q.top()){
                q.pop();
                q.push(*i);
             }
         }
         return q.top();
    }

你可能感兴趣的:(c++,数据结构与算法,c++)