携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情
4 优先队列的简单用法
C++中有这样一个STL类:它可以实现以O(1)时间复杂度取得一个列表中的最大值/最小值,然后插入也只需要O(logN)的平均时间复杂度。它就是优先队列priority_queue。虽然它的名字里面带着“队列”两个字,但是它的底层实现并非基于线性的队列,而是基于堆这一数据结构的。堆的定义是这样的:每个节点有两个孩子(默认二叉堆),每个节点都存储一个值,它的值的大小大于/小于左右两个孩子节点的值,如果所有节点都满足大于的条件,则是大根堆(又称作大顶堆),反之则是小根堆(又称为小顶堆)。priority_queue这个类在构造的时候,和vector等容器类相似,传一个数据类型,这个数据类型其实就是C++模板(template)声明中的typename,现在可以简单理解为这个容器里面装的元素都是同一个类型,就是构造时包在尖括号里的数据类型。比如:
#include <queue>
using namespace std;
priority_queue<int> q;
可以看到,虽然优先队列底层本质上不是一个线性队列,但是它还是包含在<queue>这个头文件里的。当然,这里也可以多传两个参数,形如:priority_queue<int, vector<int>, greater<int>> q;。其中第二个尖括号里的参数就是底层真正使用的容器,第三个参数就是使用的用于比较的仿函数。至于什么叫仿函数,现在可以先简单理解为让类或者结构体可以表现得像一个函数一样。那么什么叫“像函数一样”呢?一个函数比较典型的特征是可以使用()进行调用对吧?那么现在仿函数就可以实现对类使用()进行“调用”。第二个参数和第三个参数都是可选的且有默认值,也就是可以不写,不写就成了最开始举的那种例子,然后相当于第二个参数和第三个参数都用的是默认值,第二个参数的默认值就是vector<T>,第三个是less<T>。