STL 中的 heap 与 priority_queue

heap

STL 在 <algorithm.h> 中实现了对存储在 vector/deque 中的元素进行堆操作的函数,包括 make_heap, pop_heap, push_heap, sort_heap。
- make_heap

make_heap(_First,_Last,_Comp);

_First 与_Last 为可以随机访问的迭代器(指针),_Comp 为比较函数。
建立一个堆,第三个参数有默认值,默认为最大堆,当需要建立最小堆的时候 可以传入参数greater<类型>()来建立内置类型的最小堆,例如建立元素类型是 int 的最小堆:

vector<int> v = {4,5,2,1,6,8,9};
make_heap(v.begin(), v.end(), greater<int>());

如果要对自定义的类型建堆,需要自己定义比较函数传入(后面说)。
PS:为什么 “greater” 是建立最小堆啊,感觉好别扭,但自己测试了下 确实是这样…

  • push_heap
push_heap(_First, _Last,_Comp);

当有一个元素新加入容器的尾部时,用此函数调整堆。
“_Comp” 需要与之前 make_heap 保持一致。

v.push_back(3);
push_heap(v.begin(), v.end(), greater<int>());
  • pop_heap
pop_heap(_First, _Last, _Comp);

将堆顶弹出,然后调整堆。
需要注意的是,pop_heap后容器的 size 并不减少,只是将堆顶的元素置到容器的尾部。

pop_heap(v.begin(), v.end(), greater<int>());

如下图所示,第一行为操作之前的 v ,第二行为执行pop_heap 之后的 v 。

这里写图片描述

  • sort_heap
sort_heap(_First, _Last, _Comp)

堆排序,值得注意的一点是,最大堆排序结果是从小到大的,最小堆排序结果是从大到小的,这和堆排序的实现有关系。

priority_queue

简介

优先队列不是一个 STL 容器,而是一个容器适配器。它使用其他容器作为底层容器,修改了接口,实现了上面所讲的 heap 的功能。
底层容器需要满足的条件是可以通过迭代器随机访问并且支持 front() push_back() pop_back() 这些操作。因此,vectordeque可以作为priority_queue的底层容器,默认为vector
- 头文件 #include <queue>
- 定义

priority_queue<Type,Container,Functional>

Type 为数据类型,Container 为保存数据的容器,Functional 为元素的比较方式。
- 初始化
priority_queue 可以用一个数组初始化:

int a[10] = {2,5,5,1,2,7,3,7,4,8};
priority_queue<int> pq(a,a+10);

priority_queue 成员函数

priority_queue::empty 判断优先队列是否为空,调用底层容器的同名函数来实现。
priority_queue::size 返回队列元素的个数,调用底层容器的同名函数来实现。
priority_queue::top 返回队列的头元素的常引用,也就是堆顶元素,调用底层容器的成员函数 front() 来实现。
priority_queue::push 插入元素到队尾,然后调整堆。
priority_queue::emplace 也是插入新的元素,不同的是 emplace 是直接传入参数,然后调用元素类型的构造函数构造对象,然后插入到优先队列。
priority_queue::swap 交换两个队列中的元素。

使用非内置类型元素构建 priority_queue

自己定义的类型若想使用优先队列,需要自己定义数据类型的优先级,有两种实现方法:
1. 通过自定义 ‘<’ 操作符来比较元中的优先级
示例:

class Node{
public:
    int a;
    int b;
    string data;
    Node(int _a,int _b,string _data)
    {
        a = _a;
        b = _b;
        data = _data;
    }
};
bool operator < (const Node &n1,const Node &n2)
{
    if (n1.a != n2.a)
    {
        return n1.a < n2.a;
    }
    else
    {
        return n1.b < n2.b;
    }
}
int main()
{
    priority_queue<Node> pq;
    pq.emplace(3, 5, "hello1");
    pq.emplace(6, 5, "hello2");
    pq.emplace(4, 3, "hello3");
    pq.emplace(6, 3, "hello4");
    pq.emplace(6, 7, "hello5");
    cout << pq.size() << endl;
    cout << pq.top().data << endl;
    system("pause");
    return 0;
}

输出结果:

这里写图片描述

可以发现,默认构建的是最大堆,若希望构建最小堆:

priority_queue<Node,vector<Node>,greater<Node> > pq;
  1. 自定义一个比较类,重载’()’
    示例:
class Node{
public:
    int a;
    int b;
    string data;
    Node(int _a,int _b,string _data)
    {
        a = _a;
        b = _b;
        data = _data;
    }
};
struct comp {
    bool operator()(const Node &n1, const Node &n2)
    {
        if (n1.a != n2.a)
        {
            return n1.a < n2.a;
        }
        else
        {
            return n1.b < n2.b;
        }
    }
};
int main()
{
    priority_queue<Node,vector<Node>,comp> pq;
    pq.emplace(3, 5, string("hello1"));
    pq.emplace(6, 5, "hello2");
    pq.emplace(4, 3, "hello3");
    pq.emplace(6, 3, "hello4");
    pq.emplace(6, 7, "hello5");
    cout << pq.size() << endl;
    cout << pq.top().data << endl;
    system("pause");
    return 0;
}

输出结果与上面一致。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值