- binary heap
- heap算法
- push_heap算法
- pop_heap算法
binary heap是一种complete binary tree(完全二叉树),也就是说,整棵binary tree除了最底层的叶节点之外,是填满的,而最底层的叶节点由左到右又不得有空隙,如图所示:
complete binary tree整棵树内没有任何节点漏洞,这带来一个极大的好处:我们可以利用array来存储所有节点,假设动用一个小技巧,将array的#0元素保留,那么当complete binary tree中的某个节点位于array的i处时,其左节点必位于array的2i处,其右节点必位于array的2i+1处,其父节点必位于i/2处(此处的"/‘’权且代表高斯符号,取其整数),这种通过array表述tree的方式,我们称为隐式表述法
array的缺点是无法动态改变大小,以vector代替array是更好的选择
根据元素排列方式,heap可分为max—heap和min—heap两种,前者每个节点的键值都大于或等于其子节点键值,后者的每个节点键值都小于或等于其子节点键值
下图所示的是push_heap算法的实际操演情况,为了满足complete binary tree的条件,新加入的元素一定要放在最下一层作为叶节点,并填补在由左至右的第一个空格,也就是把新元素插入在底层vector的end()处
新元素是否适用于其现有位置?为满足max-heap的条件,我们执行一个所谓的percolate up(上溯)程序,将新节点拿来与其父节点比较,如果其键值比父节点大,就父子对换位置,如此一直上溯,直到不需对换或直到根结点为止
下面是算法的实现细节:
templatepop_heap算法void _push_heap(RandomAccessIterator first,Distance holeIndex,Distance topIndex,T value) { Distance parent=(holdIndex-1)/2;//找出父节点 while(holeIndex>topIndex&&*(first+parent) //当尚未到达顶端,且父节点小于新值 //由于以上使用operator<.可知STL heap是一种max-heap *(first+holeIndex)=*(first+parent);//令洞值为父值 holeIndex=parent;//调整洞号,向上提升至父节点 parent=(holeIndex-1)/2;//新洞的父节点 }//持续至顶端,或满足heap的次序特性为止 *(first+holdIndex)=value;//令洞值为新值,完成插入操作 }
如图所示:
下面是pop_heap算法的实现细节
templatevoid _adjust_heap(RandomAccessIterator first,Distance holeIndex,Distance len,T value) { Distance topIndex=holeIndex; Distance secondChild=2*holeIndex+2; while(secondChild //比较洞节点之左右两个子值,然后以secondChild代表大子节点 if(*(first+secondChild)<*(first+(secondChild-1))) secondChild--; //令较大子值为洞值,再令洞号下移至较大子节点处 *(first+holeIndex)=*(first+secondChild); holeIndex=secondChild; //找出新洞节点的右子节点 secondChild=2*(secondChild+1); } if(secondChild==len)//没有右节点,只有左节点 { *(first+holeIndex)=*(first+(secondChild-1)); holeIndex=secondChild-1; } //将欲调整值填入目前的洞号内,注意,此时肯定满足次序特性 _push_heap(first,holeIndex,topIndex,value); }
注意,pop_heap之后,最大元素只是被置放于底部容器的最尾端,尚未被取走,如果要取其值,可使用底部容器(vector)所提供的back()操作函数,如果要移除它,可使用底部容器所提供的pop_back()的操作函数



