堆的操作:
堆的操作函数定义在头文件 algorithm 中
以下的代码中均省略了输出的代码
vector<int> a{ 4,5,6,7,3,0,1 };
for (int i = 0; i < a.size(); i++)
{
cout << a[i] << ' ';
}
创建堆:堆用容器vector来存放
函数:make_heap()根据指定的迭代器区间以及一个可选的比较函数,来创建一个heap,默认创建大根堆
// 1
template< class RandomIt >
void make_heap( RandomIt first, RandomIt last );
// 2
template< class RandomIt, class Compare >
void make_heap( RandomIt first, RandomIt last, Compare comp );
vector<int> a{ 4,5,6,7,3,0,1 };
make_heap(a.begin(), a.end());
输出堆a:
指定比较函数创建大根堆:
make_heap(a.begin(), a.end(),less<int>());
指定比较函数创建小根堆:
make_heap(a.begin(), a.end(),greater<int>());
插入堆:
函数:push_heap()把指定区间的最后一个元素插入到heap中
注:在使用之前要想vector末尾中插入元素
// 1
template< class RandomIt >
void push_heap( RandomIt first, RandomIt last );
// 2
template< class RandomIt, class Compare >
void push_heap( RandomIt first, RandomIt last, Compare comp );
先用make_heap来构造一个堆,然后在容器末尾追加元素之后,把新的迭代器区间传给push_heap,这样新尾部元素也被添加到堆中。
vector<int> a{ 4,5,6,7,3,0,1 };
make_heap(a.begin(), a.end(),less<int>());
a.push_back(100);
push_heap(a.begin(), a.end());
结果:
默认使用的是大根堆的比较方式
注意:使用push_heap(f, l)的话,调用者需要确保(f, l-1)已经是一个堆. push_heap(f, l)仅仅会把*(l)插入到(f, l-1)这个区间形成的堆中
若使用的是不同的比较函数:
vector<int> a{ 4,5,6,7,3,0,1 };
make_heap(a.begin(), a.end(),less<int>());
a.push_back(100);
push_heap(a.begin(), a.end(),greater<int>());
100在插入堆使用的是小根堆的比较方式,而他的父节点4比100小,且4-3-100所形成的堆中已经是小根堆,所以就不进行替换。
弹出堆:
函数:pop_heap()弹出heap顶元素, 将其放置于区间末尾
// 1
template< class RandomIt >
void pop_heap( RandomIt first, RandomIt last );
// 2
template< class RandomIt, class Compare >
void pop_heap( RandomIt first, RandomIt last, Compare comp );
它的作用是:交换first和*(last-1), 然后把(first, last-1)建成一个max(min) heap. 也就是说把堆顶的最大元素交换到区间尾,然后把除了尾部的元素的剩余区间重新调整成堆。
vector<int> a{ 4,5,6,7,3,0,1 };
make_heap(a.begin(), a.end(),less<int>());
pop_heap(a.begin(), a.end());
int max = a.back();
a.pop_back();
注意的是,调用者要保证,在调用pop_heap时(first, last)已经是一个堆(使用相同的排序准则)。
堆排序:
函数:sort_heap()堆排序算法,通常通过反复调用pop_heap来实现
是经典的堆排序算法,通过每次弹出堆顶直到堆为空,依次被弹出的元素就组成了有序的序列了
// 1
template< class RandomIt >
void sort_heap( RandomIt first, RandomIt last );
// 2
template< class RandomIt, class Compare >
void sort_heap( RandomIt first, RandomIt last, Compare comp );
vector<int> a{ 4,5,6,7,3,0,1 };
make_heap(a.begin(), a.end(),less<int>());
sort_heap(a.begin(), a.end());
使用sort_heap(f, l)处理过的区间因为已经有序,就不再是一个最大堆或者是最小堆了。
判断堆:
函数:is_heap()判断给定区间是否是一个最大堆或者最小堆//是返回1,不是返回0
//1 (since C++11)
template< class RandomIt >
bool is_heap( RandomIt first, RandomIt last );
//2 (since C++11)
template< class RandomIt, class Compare >
bool is_heap( RandomIt first, RandomIt last, Compare comp );
vector<int> a{ 4,5,6,7,3,0,1 };
bool flag = is_heap(a.begin(), a.end());
cout << "before heap a:";
if (flag)
cout << "此时堆是一个最大堆或者最小堆" << endl;
else cout << "此时堆不是一个最大堆或者最小堆" << endl;
make_heap(a.begin(), a.end(),less<int>());
flag = is_heap(a.begin(), a.end());
cout << "after heap a:";
if (flag)
cout << "此时堆是一个最大堆或者最小堆" << endl;
else cout << "此时堆不是一个最大堆或者最小堆" << endl;
判断堆并返回第一个不满足条件的位置:
函数:is_heap_until()
//1 (since C++11)
template< class RandomIt >
RandomIt is_heap_until( RandomIt first, RandomIt last );
//2 (since C++11)
template< class RandomIt, class Compare >
RandomIt is_heap_until( RandomIt first, RandomIt last, Compare comp );
vector<int> a{ 4,5,6,7,3,0,1 };
auto iter = is_heap_until(a.begin(), a.end());
cout << "iter:" << *iter << endl;
我们可以自己分析得到在3的位置就不满足小根堆的规律,在3之前的元素满足小根堆的规律,所以iter应该是5