【C++ STL】优先级队列(priority_queue)详解

一、介绍

  priority_queue是一种队列,其中每个元素都被赋予一个优先级。在优先级队列中,元素以优先级顺序出队,而不是按插入顺序出队。也就是说,优先级最高的元素最先出队
  priority_queue的声明在<queue>中。
在这里插入图片描述

  • 从上可以看到,priority_queuestackqueue都是容器适配器,且priority_queue的底层默认容器vector
  • priority_queue的第三个模板参数class Compare = less<...>是一个仿函数。在C++中,仿函数是一种类,它重载了函数调用运算符operator(),从而使得它的对象可以像函数一样被调用。除此之外,仿函数还可以携带状态(即成员变量),这使得它比普通的函数指针更为灵活。
      那说了这么多,优先级队列到底是个什么东西,其实它就是我们在c语言数据结构阶段学习的堆(Heap),默认情况下是最大堆。既然是堆,那插入和删除操作的时间复杂度都为O(logn)。

二、接口

  priority_queue是一个模板类,提供了以下接口:

  • 构造函数:可以用默认构造函数、带比较器的构造函数、用一对迭代器初始化的构造函数等。
  • 成员函数
      push(const value_type& val):插入元素。
      pop():移除优先级最高的元素。
      top():返回优先级最高的元素。
      empty():检查队列是否为空。
      size():返回队列中的元素数量。
    以下是一个使用priority_queue的示例:
#include <iostream>
#include <queue>
#include <vector>

int main() {
    // 创建一个最小堆
    std::priority_queue<int, std::deque<int>, std::greater<int>> min_pq;

    // 插入元素
    min_pq.push(10);
    min_pq.push(30);
    min_pq.push(20);
    min_pq.push(5);
    min_pq.push(1);

    // 输出并移除优先级最高的元素
    std::cout << "按优先级顺序排列的元素: ";
    while (!min_pq.empty()) {
        std::cout << min_pq.top() << " ";
        min_pq.pop();
    }
    std::cout << std::endl;

    return 0;

输出:

按优先级顺序排列的元素 (min-heap): 1 5 10 20 30

  priority_queue的底层容器需要支持随机访问迭代器以及上面的那些接口,因此vectorduque都能满足这些需求。

三、priority_queue的简单模拟实现

  priority_queue的底层结构就是,因此此处只需对对进行通用的封装即可。

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

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

template <class T, class Container = vector<T>, class Compare = less<T> >
class priority_queue
{
public:
    void AdjustUp(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;
        }
    }

    void AdjustDown(int parent)
    {
        int child = parent * 2 + 1;
        while (child < _c.size())
        {
            if (child + 1 < _c.size() && _comp(_c[child], _c[child + 1]))
            {
                child = child + 1;
            }

            if (_comp(_c[parent], _c[child]))
            {
                swap(_c[parent], _c[child]);
                parent = child;
                child = parent * 2 + 1;
            }
            else
                break;
        }
    }

    priority_queue() // 空构造
        : _c()
    {}

    template <class InputIterator>
    priority_queue(InputIterator first, InputIterator last) // 用迭代器区间构造
    {
        while (first != last)
        {
            _c.push_back(*first);
            AdjustUp(_c.size() - 1);
            ++first;
        }
    }

    bool empty() const
    {
        return _c.empty();
    }

    size_t size() const
    {
        return _c.size();
    }

    const T& top() const
    {
        return _c.front();
    }

    void push(const T& x)
    {
        _c.push_back(x);
        AdjustUp(_c.size() - 1);
    }

    void pop()
    {
        swap(_c[0], _c[_c.size() - 1]);
        _c.pop_back();
        AdjustDown(0);
    }

private:
    Container _c;
    Compare _comp;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值