heap不属于STL容器组件,它作为一种底层机制,可以对vector、list等容器进行操作,使其符合“堆”的特性:允许用户以任何次序将任何元素推入容器,但取出时一定是从优先权最高的元素开始取。
所谓binary heap相当于一种完全二叉树,整棵树除了底层的叶节点之外,都是填满的,而最底层的叶节点由左到右不得有空隙。由于整棵树没有任何节点漏洞,带来一个极大的好处:可以使用array来储存所有节点。假如使用一个小技巧,将array的#0元素保留(或设为无限大值或无限小值),那么某个节点位于array中的i号索引时,其左子节点必们于array的2i处,其右子节点必位于array的2i+1处,其父节点必位于i/2处。不过,SGI STL中并没有使用该技巧。
push_heap的关键算法如下,注意,在调用push_heap之前,新元素必须已经插入array的尾端:
Distance parent = (holeIndex - 1) / 2;// 求出新元素当前的父节点索引,holeIndex为新元素的索引
while( holeIndex > topIndex && *( first + parent) < value) {
// 如果尚未到达顶端,并且父节点小于新值(显然STL heap是一种max-heap)
// 就令洞值为父节点值,并持续向上搜索
*(first + holeIndex) = *(first + parent);
holeIndex = parent;
parent = ( holeIndex - 1) / 2;
}
*(first + holeIndex) = value; // 找到了新元素的合理位置,完成插入操作
heap的用法:
int ia[9] = { 0, 1, 2, 3, 4, 8, 9, 3, 5}; vector<int> ivec(ia, ia+9); make_heap(ivec.begin(), ivec.end()); // 把array容器转换成heap,转换后容器内容为{ 9, 5, 8, 3, 4, 0, 2, 3, 1} ivec.push_back(7); push_heap(ivec.begin(), ivec.end()); // 把新元素推入堆中,注意新元素必须事先添加到容器里{9, 7, 8, 3, 5, 0, 2, 3, 1, 4} pop_heap(ivec.begin(), ivec.end()); // 把堆的根节点(即容器的0号元素)放到容器的最尾端{8, 7, 4, 3, 5, 0, 2, 3, 1, 9} ivec.pop_back(); // {8, 7, 4, 3, 5, 0, 2, 3, 1} sort_heap(ivec.begin, ivec.end()) // 对堆排序,注意排序后就失去堆特性了{0, 1, 2, 3, 3, 4, 5, 7, 8}