将数组heap看成完全二叉树,用heap的索引按层序给完全二叉树编号,编号为i的节点的值对应heap[i]的值,那么二叉树的根、左、右节点编号满足left=2root+1,right=2root+2,按照这个规则访问数组就像在访问二叉树,再将二叉树构建成所有根节点都大于等于左右子节点。

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

template <typename T>
class myHeap
{
private:
    vector<T> heap;
    void swap(T &a, T &b)
    {
        T tmp = a;
        a = b;
        b = tmp;
    }
    // pop后向下递归调整 最差O(logn)
    void down_adjust(int root)
    {
        int left = 2 * root + 1;
        int right = 2 * root + 2;
        int largest = root;
        //找到根、左、右中最大值的索引
        if (left < heap.size() && heap[left] > heap[largest])
            largest = left;
        if (right < heap.size() && heap[right] > heap[largest])
            largest = right;
        if (largest != root)
        {
            swap(heap[largest], heap[root]);
            down_adjust(largest); //继续递归调整左子节点或者右子节点
        }
    }
    // push后向上调整 最差O(logn)
    void up_adjust()
    {
        int last = heap.size() - 1; //最后一个节点
        int root = (last - 1) / 2;  //最后一个节点的父节点
        // push的元素被调整到堆顶或者小于等于根时退出循环
        while (root >= 0 && heap[last] > heap[root])
        {
            swap(heap[last], heap[root]);
            last = root;
            root = (root - 1) / 2;           
        }
    }
    //从数组构建堆O(n)
    void construct()
    {
        //从最后一个根节点开始调整
        for (int i = (heap.size() - 2) / 2; i >= 0; i--)
        {
            down_adjust(i);
        }
    }

public:
    void push(T val)
    {
        heap.push_back(val);
        up_adjust();
    }
    T pop()
    {
        T tmp = heap[0];
        heap[0] = heap.back();
        heap.pop_back();
        down_adjust(0);
        return tmp;
    }
    T top()
    {
        return heap[0];
    }
    bool empty()
    {
        return heap.size() == 0;
    }
};

int main()
{
    int n;
    cin >> n;
    string opt;
    int val;
    myHeap<int> mh;
    for (int i = 0; i < n; i++)
    {
        cin>>opt;
        if(opt=="push"){
            cin >> val;
            mh.push(val);
        }
        else if(opt=="pop"){
            if(mh.empty())
                cout << "empty" << endl;
            else
                cout << mh.pop() << endl;
        }
        else{
            if(mh.empty())
                cout << "empty" << endl;
            else
                cout << mh.top() << endl;
        }
    }
}