*
    image.png
    设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边。
    编号为i的子节点:
    左孩子编号:2
    i
    右孩子编号:2 * i + 1
    完全二叉树可以用连续的空间存储,根据节点与子孩子之间编号的建立关系。


    image.png
    image.png
    堆分为大根堆与小根堆:
    小根堆父节点的值小于子节点的值,大根堆是父节点的值大于子节点的值。

    大根堆插入:
    从数组最末尾插入,然后向上进行调整:(数组下标从0开始,因此根结点与左右孩子的关系不再是上面提到的)
    父节点:i
    左孩子:2 i + 1
    右孩子:2
    i + 2

    1. void push(int x) {
    2. data[cnt++] = x;
    3. int ind = cnt - 1;
    4. while (ind > 0 && data[(ind - 1) / 2] < data[ind]) {
    5. swap(data,ind,(ind - 1) / 2);
    6. ind = (ind - 1) / 2;
    7. }
    8. }

    大根堆弹出:
    从数组开头弹出,然后将末尾节点补到数组开头,再进行向下调整

    1. void pop() {
    2. if(cnt == 0) return;
    3. swap(data,0,cnt - 1);
    4. cnt--;
    5. int ind = 0,n = cnt - 1;
    6. while (2 * ind + 1 <= n) {
    7. /**
    8. * 找到三元组中最大的值
    9. */
    10. int temp = ind;
    11. if(data[temp] < data[ind * 2 + 1]) temp = ind * 2 + 1;
    12. if(2 * ind + 2 <= n && data[temp] < data[ind * 2 + 2]) temp = 2 * ind + 2;
    13. if(ind == temp) break;//当前就是最大的值,不需要再向下调整
    14. swap(data,temp,ind);
    15. ind = temp;
    16. }
    17. }