1.原理
最大最小堆的定义:
- 它是一颗完全二叉树,它可以是空
- 树中结点的值总是不小于(不大于)其孩子结点的值
- 每一个结点的子树也是一个堆
当父结点的键值总是大于或等于任何一个子结点的键值时为:最大堆。
当父结点的键值总是小于或等于任何一子节点的键值时:最小堆.
例如下图就是一个最大堆。最大堆的每一条路径都是由大到小的。
最大堆的构建、插入、移除操作的原理及其代码,参考简书:最大堆和最小堆
2.在c++算法库中的使用
2.1介绍
最大最小堆在c++中相关的函数是:
make_heap(), pop_heap(), push_heap()
它们包含在头文件<algorithm>
中
1)make_heap
在容器范围内,就地建堆,保证最大(小)值在所给范围的最前面,其他值的位置不确定。
可以有两个参数,也可以有三个参数,前两个参数是指向开始元素的迭代器和指向结束元素的下一个元素的迭代器。第三个参数是可选的,不选默认大顶堆。我们可以自定义比较函数来设定小顶堆,比如auto cmp = [](const int x, const int y) { return x > y;};
。
2)pop_heap
将堆顶(所给范围的最前面)元素移动到所给范围的最后,并且将新的最大(小)值置于所给范围的最前面。
3)push_heap
在堆的基础上进行数据的插入操作。需要注意的是,只有make_heap()和push_heap()同为大顶堆或小顶堆,才能插入。
2.2使用案例:
大顶堆:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> nums = { 4, 5, 1, 3, 2 };
// generate heap in the range of numsector
make_heap(nums.begin(), nums.end());
cout << "initial max value : " << nums.front() << endl;
// pop max value
pop_heap(nums.begin(), nums.end());
nums.pop_back();
cout << "after pop, the max vsalue : " << nums.front() << endl;
// push a new value
nums.push_back(6);
push_heap(nums.begin(), nums.end());
cout << "after push, the max value : " << nums.front() << endl;
system("pause");
return 0;
}
结果:
initial max value : 5
after pop, the max vsalue : 4
after push, the max value : 6
小顶堆:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
// define cmp function
auto cmp = [](const int x, const int y) { return x > y; };
vector<int> nums2 = { 40, 50, 10, 30, 20 };
// generate heap in the range of numsector
make_heap(nums2.begin(), nums2.end(), cmp);
cout << "initial min value : " << nums2.front() << endl;
// pop max value
pop_heap(nums2.begin(), nums2.end(), cmp);
nums2.pop_back();
cout << "after pop, the min vsalue : " << nums2.front() << endl;
// push a new value
nums2.push_back(0);
push_heap(nums2.begin(), nums2.end(), cmp);
cout << "after push, the min value : " << nums2.front() << endl;
system("pause");
return 0;
}```
```bash
initial min value : 10
after pop, the min vsalue : 20
after push, the min value : 0
3.最大(小)堆实例应用
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
参考代码如下:
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//方法:最大堆方法 O(nlogk)
int len=input.size();
if( len<=0 ||k<=0 ||k>len )
return vector<int>();
vector<int> res(input.begin(), input.begin()+k );
//建堆
make_heap(res.begin(),res.end());
for(int i=k;i<len;i++)
{
if(input[i]<res[0])
{
//先pop,然后在容器中删除
pop_heap(res.begin(),res.end());
res.pop_back();
//先在容器中加入,再push
res.push_back(input[i]);
push_heap(res.begin(),res.end());
}
}
//使其从小到大输出
sort_heap(res.begin(),res.end());
return res;
}
};
参考
牛客网
c++ make_heap(), pop_heap()函数
c++ make_heap(), push_heap(),pop_heap()函数