1.概念

堆是一种完全二叉树(除了最底层,其它层都必须填满,最后一层可以从左到右填满),堆的每一个节点都有一个值。

数据结构里的堆是由一些按照某种优先级来组织成的队列,所以堆又叫做优先队列,在STL中可以用priority_queue实现。

2.分类

堆可以分为最大堆和最小堆:

  • 最大堆:每个父节点都大于各孩子节点

  • 最小堆:每个父节点都小于各孩子节点

    3.存储和性质

    堆是一棵完全二叉树,所以使用数组可以高效的存储数据。

性质

  • 对于一个非根节点的节点 i 来说,如果它的下标为 k,那么它的父节点的下标为 (k -1)/2,子节点的下标为2 *k +1和2 *k + 2
  • 每个结点的左子树和右子树都是一个二叉堆
4.堆的实现

现有数组 int* a={10,5,7,12,13,11,20,25,14,30};
根据这个数组建出一个带值的完全二叉树。在这里插入图片描述
现在我们要使这个完全二叉树变成最大堆,就是让整棵树中的双亲节点都大于孩子节点。所以我们要从叶子结点开始调整,直到调整到根节点结束

template<class T>
struct Less {
    bool operator()(const T& a,const T& b) {
        return a<b;
    }
};
template<class T>
struct Greater {
    bool operator()(const T& a,const T& b) {
        return a>b;
    }
};

template<typename T,class com = Greater<int>>
class Heap {
public:
    //构造函数
    Heap(){}
    //建堆
    Heap(T* a, size_t n)
        :_a(a,a+n) {
        for (int i = (_a.size()-2)/2; i>=0; i--) {
            _Adjustdown(i);
        }
    }
    //尾插
    void Push(const T& x) {
        _a.push_back(x);
        _Adjustup(_a.size()-1);
    }
    //尾删
    void Pop() {
        swap(_a[0],_a[_a.size()-1]);
        _a.pop_back();
        _Adjustdown(0);
    }
    //求堆里元素的个数
    size_t Size() {
        return _a.size();
    }
    //求堆顶的元素
    T& Top() {
        return _a[0];
    }
    //判断堆是否为空
    bool Empty() {
        return _a.size()==0;
    }

protected:
    void _Adjustdown(int root) {//下调
        int parent = root;
        int child = parent*2+1;
        while (child<_a.size()) {
            //找左右孩子中值最大的
            if (child+1<_a.size() && com()(_a[child+1],_a[child])) {
                ++child;
            }
            //将孩子和父母做比较
            if (com()(_a[child],_a[parent])) {
                swap(_a[child],_a[parent]);
                parent = child;
                child = parent*2+1;
            } else {
                break;
            }
        }
    }
    //上调
    void _Adjustup(int i) {
        //Compare com;
        int child = i;
        int parent = (i-1)/2;
        while (child >= 0) {
            if (com()(_a[child] , _a[parent])) {
                swap(_a[child],_a[parent]);
                child = parent;
                parent = (parent-1)/2;
            } else {
                break;
            }
        }
    }
  protected:
      vector<T> _a;
};
template<class T,class com = Greater<int>>
class PriorityQueue {
  public:
    //构造函数
      PriorityQueue() {}
      void Push_Back(const T& x) {
        _hp.Push(x);
    }
      void Pop_Front() {
          _hp.Pop();
      }
      size_t PQ_Size() {
          return _hp.Size();
      }
      T& PQ_Top() {
          return _hp.Top();
      }
      bool PQ_Empty() {
          return _hp.Empty();
      }
  protected:
      Heap<T,com> _hp;
};