1、头文件:algorithm
对make_heap(), pop_heap(), push_heap()的用法做个总结:
make_heap()生成堆,他有两个参数,也可以有三个参数,前两个参数是指向开始元素的迭代器和指向结束元素的下一个元素的迭代器。第三个参数是可选的,可以用伪函数less()和greater()来生成大顶堆和小顶堆,其中type为元素类型。如果只传入前两个参数,默认是生成大顶堆。
push_heap()是在堆的基础上进行数据的插入操作,参数与make_heap()相同,需要注意的是,只有make_heap()和push_heap()同为大顶堆或小顶堆,才能插入。
pop_heap()是在堆的基础上,弹出堆顶元素。这里需要注意的是,pop_heap()并没有删除元素,而是将堆顶元素和数组最后一个元素进行了替换,如果要删除这个元素,还需要对数组进行pop_back()操作。
案例:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> nums = { 4, 5, 1, 3, 2 ,8 ,7};
// generate heap in the range of numsector
make_heap(nums.begin(), nums.end(),less<int>());
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;
}
2、经典题目(TOP K):
最大堆O(nlogk)
-
首先选取前K个数建立最大堆(根结点值大于左右结点值)。
-
此后,每次从原数组中取一个元素与根进行比较,如果大于根结点的元素,忽视之,取下一个数组元素继续该过程;如果小于根结点的元素,则将其加入最大堆,并进行堆调整,将根元素移动到最后再删除,即保证最大堆中的元素仍然是排名前K的数,且根元素仍然最大。
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
int sz = input.size();
vector<int> vec;
if (sz == 0 || k <= 0 || sz < k)
return vec;
for (int i = 0; i < k; ++i)
vec.push_back(input[i]);
// 以数组前k个元素建立初始的最大堆
make_heap(vec.begin(), vec.end(), less<int>());
for (int i = k; i < sz; ++i)
{
if (input[i] > vec.front()) // 如果接下来的元素比堆顶元素大,直接跳过
continue;
else // 如果接下来的元素比堆顶元素小,则调整堆
{
vec.push_back(input[i]);
// 添加新元素调整堆
push_heap(vec.begin(), vec.end());
// 将堆顶元素调整到最后
pop_heap(vec.begin(), vec.end());
// 删除最后那个元素
vec.pop_back();
}
}
// 以上方法得到的只是求了TopK,但是并未排序,所以使用sort_heap排序一下
sort_heap(vec.begin(), vec.end());
return vec;
}
};
int main()
{
//4、5、1、6、2、7、3、8
vector<int>vec;
vec.push_back(4);
vec.push_back(5);
vec.push_back(1);
vec.push_back(6);
vec.push_back(2);
vec.push_back(7);
vec.push_back(3);
vec.push_back(8);
Solution s;
vector<int>result = s.GetLeastNumbers_Solution(vec, 4);
for (vector<int>::iterator it = result.begin(); it != result.end(); it++)
{
cout << *it << endl;
}
system("pause");
return 0;
}
【该算法有两个明显的优点】:
没有修改输入的数据(代码中的变量data)。我们每次只是从data中读入数字,所有的写操作都是在容器leastNumbers中进行的。
该算法适合海量数据的输入,不需要将数据一次性全部载入内存。