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()
这些操作。因此,vector
与deque
可以作为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;
- 自定义一个比较类,重载’()’
示例:
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;
}
输出结果与上面一致。