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()函數