1. 什么是堆(heap)

堆(heap)是一种数据结构,我们可以通过堆,方便的找到数据中最大或最小的数。它的pop_max操作(弹出最大值,整个堆重新heapify)算法复杂度是O(logN)

2. 如何建立一个堆

在c++中已经有建立好的数据结构,方便我们实现堆,堆本质是一种特殊的存储方式,它实质的载体是数组等一些的容器。在c++中调用 #include <queue>中的template <class T, class Container = vector<T>,class Compare = less<typename Container::value_type> > class priority_queue;

比如我们给定一组数[3,2,5,7,9,1],想让这组数构成一个大根堆,每次弹出最大的数:

#include <queue>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main(int argc, char const *argv[]){
    // 创建默认的大根堆
    priority_queue<int> big_heap;
    big_heap.push(3);
    big_heap.push(2);
    big_heap.push(5);
    big_heap.push(7);
    big_heap.push(9);
    big_heap.push(1);

    while( !big_heap.empty()){
        cout << big_heap.top() << " , " ;
        big_heap.pop();
}
return 0;}

输出:9 , 7 , 5 , 3 , 2 , 1
在c++中默认的priority_queue就是一个大根堆,如果想要使用小根堆就要把后面的Compare写成greater比较器:

priority_queue<int, std::vector<int>, greater<int>> small_heap;

输出:1 , 2 , 3 , 5 , 7 , 9

3.特殊结构的堆

如果堆中的数据不是直接可以比较的类型(int,double,long),而是一个结构体呢?如果我们不重写Compare,将会出错 error: invalid operands to binary expression ('const student' and 'const student'){return __x < __y;},因为student根本无法比较。
这里我们有两种方法可以改写Compare:

  1. 重载运算符 operator <
# include <queue>
# include <iostream>
# include <string>
#include <vector>
using namespace std;

struct student
{
    int id;
    string name;
    int age;
};

// 直接重载运算符 < 
bool operator< (student a, student b){
     return a.age < b.age;
}

int main(int argc, char const *argv[])
{
    /* code */
    student s1 = {1, "到处露鸟", 26};
    student s2 = {3, "尿尿不洗手", 18};
    student s3 = {2, "便秘女孩", 17};

    //priority_queue<student, std::vector<student>, cmp > students;

    priority_queue<student> students;

    students.push(s1);
    students.push(s3);
    students.push(s2);

    while(!students.empty()){
            cout << students.top().id << ',' << students.top().name << ',' << students.top().age <<endl;
        students.pop();
    }

    return 0;
}

输出:按照年龄的大根堆
1,到处露鸟,26
3,尿尿不洗手,18
2,便秘女孩,17

  1. 用结构体重载 operator()
// 结构体重载运算符()
struct cmp
{
    bool operator()(student x, student y){
        return x.age < y.age;
    }
};

int main(int argc, char const *argv[])
{
    /* code */
    student s1 = {1, "到处露鸟", 26};
    student s2 = {3, "尿尿不洗手", 18};
    student s3 = {2, "便秘女孩", 17};
    student s4 = {5, "便秘男孩", 20};
    student s5 = {4, "露屁屁", 28};

    priority_queue<student, std::vector<student>, cmp > students;

    //priority_queue<student> students;

    students.push(s1);
    students.push(s3);
    students.push(s2);
    students.push(s5);
    students.push(s4);

    while(!students.empty()){
        cout << students.top().id << ',' << students.top().name << ',' << students.top().age <<endl;
        students.pop();
    }

    return 0;
}

输出:
4,露屁屁,28
1,到处露鸟,26
5,便秘男孩,20
3,尿尿不洗手,18
2,便秘女孩,17
第二种的原因是,在STL中的数据结构的比较是用 operator()定义