最小堆和最大堆
简介
最大最小堆在c++中相关的函数是:
make_heap(), pop_heap(), push_heap()
它们包含在头文件中
1)make_heap(建堆)
在容器范围内,就地建堆,保证最大(小)值在所给范围的最前面,其他值的位置不确定。
可以有两个参数,也可以有三个参数,前两个参数是指向开始元素的迭代器和指向结束元素的下一个元素的迭代器。第三个参数(谓词)是可选的,不选默认大顶堆。我们可以自定义比较函数来设定小顶堆
2)pop_heap(取出)
将堆顶(所给范围的最前面)元素移动到所给范围的最后,并且将新的最大(小)值置于所给范围的最前面。
3)push_heap(插入)
在堆的基础上进行数据的插入操作。需要注意的是,只有make_heap()和push_heap()同为大顶堆或小顶堆,才能插入。
实例
/*
* c++实现最大堆(默认)or最小堆,以及对自定义数据结构实现最大堆(默认)or最小堆
*/
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
/*
* 按照学生的数学成绩进行排序
*/
class student {
public:
int math;
int english;
student(int math,int english) {
this->math = math;
this->english = english;
}
};
//仿函数
class my_conpare {
public:
bool operator()(student s1, student s2) {
return s1.math > s2.math;
}
};
void my_print(student s) {
cout << "math_score:" << s.math << endl;
cout << "english_score:" << s.english << endl;
cout << "---------------------" << endl;
}
int main() {
student s1(45, 50),s2(55,56),s3(23,100);
vector<student> v = { s1,s2,s3 };
//利用三个学生创建最小堆
make_heap(v.begin(), v.end(), my_conpare());
//遍历查看结果
cout << "第一次遍历:" << endl;
for_each(v.begin(), v.end(), my_print);
//现在取出堆顶元素(删除操作)
//1.将堆顶元素放在最后,将新的最值放在堆顶,方便v.pop_back()取出
pop_heap(v.begin(), v.end(), my_conpare());
student s = *(v.end() - 1);
cout << "取出堆顶元素:";
cout << "math_score:" << s.math << endl;
cout << "english_score:" << s.english << endl;
cout << "---------------------" << endl;
v.pop_back();
cout << "第二次遍历:" << endl;
for_each(v.begin(), v.end(), my_print);
//现在进行(插入操作)
student s4(0, 0);
v.push_back(s4);
push_heap(v.begin(), v.end(), my_conpare());
cout << "第三次次遍历:" << endl;
for_each(v.begin(), v.end(), my_print);
}
运行结果:
math_score:45
english_score:50
---------------------
取出堆顶元素:math_score:23
english_score:100
---------------------
第二次遍历:
math_score:45
english_score:50
---------------------
math_score:55
english_score:56
---------------------
第三次次遍历:
math_score:0
english_score:0
---------------------
math_score:55
english_score:56
---------------------
math_score:45
english_score:50
---------------------
2023-11-28 更新
发现了一种更简单的实现方法
/*
* c++实现最大堆(默认)or最小堆,以及对自定义数据结构实现最大堆(默认)or最小堆
*/
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
/*
* 按照学生的数学成绩进行排序
*/
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
class student
{
public:
int math;
int english;
student(int math, int english)
{
this->math = math;
this->english = english;
}
};
class my_compare
{
public:
bool operator()(student s1, student s2)
{
return s1.math > s2.math;
}
};
void my_print(student s)
{
cout << "math_score:" << s.math << endl;
cout << "english_score:" << s.english << endl;
cout << "---------------------" << endl;
}
int main()
{
// 创建一个最大堆(默认)
std::priority_queue<int> maxHeap;
// 插入元素
maxHeap.push(5);
maxHeap.push(2);
maxHeap.push(8);
maxHeap.push(1);
// 1 访问堆顶元素,输出:8
std::cout << "Top element: " << maxHeap.top() << "\n";
maxHeap.pop();
// 2 插入元素
maxHeap.push(3);
std::cout << "insert element : 3" << std::endl;
// 输出:5 3 2 1
std::cout << "Remaining elements: "<<endl;
while (!maxHeap.empty())
{
std::cout << maxHeap.top() << " ";
maxHeap.pop();
}
student s1(45, 50), s2(55, 56), s3(23, 100);
// 创建最小堆
priority_queue<int, vector<student>, my_compare> minHeap;
minHeap.push(s1);
minHeap.push(s2);
minHeap.push(s3);
// 删除操作
student s = minHeap.top();
minHeap.pop();
cout << "get the top element:"<<endl;
cout << "math_score:" << s.math << endl;
cout << "english_score:" << s.english << endl;
cout << "---------------------" << endl;
// 插入操作
student s4(0, 0);
minHeap.push(s4);
// 剩下的元素
cout << "remaining elements:";
while (minHeap.size())
{
student s = minHeap.top();
minHeap.pop();
cout << "get the element:";
cout << "math_score:" << s.math << endl;
cout << "english_score:" << s.english << endl;
cout << "---------------------" << endl;
}
return 0;
}
运行结果:
math_score:45
english_score:50
---------------------
取出堆顶元素:math_score:23
english_score:100
---------------------
第二次遍历:
math_score:45
english_score:50
---------------------
math_score:55
english_score:56
---------------------
第三次次遍历:
math_score:0
english_score:0
---------------------
math_score:55
english_score:56
---------------------
math_score:45
english_score:50
---------------------