STL之堆和堆排序(heap)
使用注意:
- 堆函数所在的头文件是
#include <algorithm>
- 堆函数操作的基础是vector,所以如果要使用heap那么则需要利用vector才能对其进行操作;我们无法创建一个heap,而是先创建一个vector,然后将vector里面的数据按照堆排序。
- heap中包含的操作函数一共有4种,分别是:
make_heap( ):建立堆(要么大顶堆,要么小顶堆)
push_heap( ): 在堆中添加元素
pop_heap( ): 在堆中删除元素
sort_heap( ): 堆排序
具体用法
1. 建堆
make_heap(_First, _Last, _Comp)
默认是建立大最大堆的。
大顶堆,就将上面的第三个参数换成:less<int>(),假如元素是int类型的;
小顶堆,就将上面的第三个参数换成:greater<int>(),假如元素是int类型的
【使用样例】
//heap set map函数的使用
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin>>n;
int a[n];
for(int i=0;i<n;i++)
cin>>a[i];
vector<int> va(a,a+n);
cout<<"开始时:"<<endl;
for(int i=0;i<n;i++)
cout<<va[i]<<" ";
cout<<endl;
make_heap(va.begin(),va.end());//此时默认建立的是大根堆
cout<<"大根堆:"<<endl;
for(int i=0;i<n;i++)
cout<<va[i]<<" ";
cout<<endl;
/*对int类型,可以在第三个参数传入greater<int>()得到最小堆*/
make_heap(va.begin(),va.end(),greater<int>());
cout<<"小根堆:"<<endl;
for(int i=0;i<n;i++)
cout<<va[i]<<" ";
cout<<endl;
return 0;
}
2. 在堆中增加元素
push_heap(_First, _Last,_Comp)
要先在底层容器(数组或vector)里加入数据,再调用push_heap()。
实现细节:(1)添加元素到vector的尾部;(2)重新调整堆。
该算法必须是在满足堆序的条件下,添加元素。
如,插入15到当前的大根堆里,vector容器名字为max_heap:
max_heap.push_back(15);
push_heap(max_heap.begin(), max_heap.end());
3. 在堆中删除元素
pop_heap(_First, _Last,_Comp)
实现细节:(1)删除堆顶元素;(2)用尾部元素替代max_heap[0];(3)重新调整堆。
(pop_heap操作实际上是我们把堆顶元素取出来,放到了数组或vector容器的末尾,用原来的末尾元素去替代,然后end迭代器减1,执行siftdown()下溯函数来重新调整堆)
注意算法执行完毕后,最大的元素并没有被取走,而是放于底层容器的末尾。如果要取走,则可以使用底部容器(vector)提供的pop_back()函数。
pop_heap()操作后,再调用max_heap.pop_back(),从底层容器中删掉原堆顶元素。
pop_heap(max_heap.begin(), max_heap.end());//取出了堆顶元素(也叫删除堆顶元素),放到了底层容器的末尾,原来末尾的元素替代堆顶,end迭代器减1,重新siftdown了堆
max_heap.pop_back();//从底层容器(数组或vector)中删除了元素
4. 堆排序
sort_heap(_First, _Last,_Comp)
既然每次pop_heap可以获得堆顶的元素(假如是大顶堆,每次都获得最大的元素,取出放到了底层容器的末尾),那么我们持续对整个heap做pop_heap操作,每次讲操作的范围向前缩减一个元素(就是每次end迭代器减1)。最终我们可以获得一个递增的序列。
注意:这个排序是在一个堆上进行的。