Heap---堆的基本结构

来源:互联网 发布:oracle 锁表sql 编辑:程序博客网 时间:2024/06/15 19:49

堆数据结构是一种数组对象,可以被视为一颗完全二叉树。

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

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

如上图为小堆存储:


下面编写堆的基本代码:

#include<iostream>#include<vector>#include<assert.h>using namespace std;template<class T>   //利用仿函数,可以完成代码的复用,这里我们假设建立大堆。struct Greater{bool operator()(const T& x1, const T& x2){return x1 > x2;}};template<class T>struct Less{bool operator()(const T& x1, const T& x2){return x1 < x2;}};template<class T,class Compare>   //堆基本结构class Heap{public:Heap(){}Heap(T* a, size_t n){_a.reserve(n);for (size_t i = 0; i < n; ++i){_a.push_back(a[i]);}//建堆//O(N*lgN)for (int i = (_a.size() - 2) / 2; i >= 0; --i)  //这里i的初始值是先找到最后一个孩子的下标,再通过计算得出第一个父亲的下标{_AdjustDown(i); //向下调整算法}}void Push(const T& x)//插入一个数{_a.push_back(x);_AdjustUp(_a.size() - 1);//向上调整算法}void Pop()//删除{assert(!_a.empty());swap(_a[0], _a[_a.size() - 1]);//把要删除的_a[0}与最后一个下标交换
_a.pop_back();  //删除交换后的最后的数
                _AdjustDown(0);  // 从0这个位置向下调整}const T& Top()   //取堆顶的数--》_a[0]{return _a[0];}size_t Size(){return _a.size();}bool Empty(){return _a.empty();}protected:void _AdjustDown(size_t root)//向下调整{Compare com;size_t parent = root;  //把root传给父亲size_t 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(size_t i)//向上调整算法{Compare com;int child = i;     //确定最后一个孩子的下标int parent = (child - 1) >> 2;  //找到父亲的下标while (parent >= 0)      //循环条件  一直往上调,直到父亲的下<0停止循环
{if (child + 1 < _a.size() && com(_a[child + 1] ,_a[child]))//比较左右孩子,找到大的孩子下标{++child;}if(com(_a[child],_a[parent]))      //如果孩子值比父亲大{swap(_a[child], _a[parent]);  //交换父子值child = parent;              //向上调整  ,将父亲下标给孩子parent = (child - 1) >> 2;  // 更新父亲的下标}  else{break;}}}vector<T> _a;};

这里我们需要注意的是  父亲下标=(孩子下标-1)/2         parent=(child-1)>>2

                                          左孩子下标=(父亲下标)*2+1    child=parent*2+1