算法描述
就Heap算法而言,heap是一种特殊的元素组织方式,应用于heap排序法(heapsort).heap可以被视为一个以序列式群集实作而成的二叉树,本文以“大堆顶”为例进行讨论,heap具有两大性质:
1、第一个元素总是最大。
2、总是能够在对数时间内增加或移除一个元素。
为了处理heap,STL提供四种算法:
1、make_heap() 将某区间内的元素转化成heap
2、push_heap() 对着heap增加一个元素
3、pop_heap() 对着heap取出下一个元素
4、sort_heap() 将heap转化为一个已序群集 (此后它就不再是heap 了)。
make_heap
void make_heap(RandomAccessIterator beg, RandomAccessIterator end); void make_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op);
- 两种形式都将区间[beg, end)内的元素都转化为heap。
- op是可选的二元判断式,被视为排序准则:op(elem1, elem2)
push_heap
void push_heap(RandomAccessIterator beg, RandomAccessIterator end); void push_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op);
- 两种形式都将end之前的最后一个元素加入原本就是个heap的[beg, end -1)区间内,使整个区间[beg, end)称为一个heap
- op是可选的二元判断式,被视为排序准则:op(elem1, elem2)
- 调用者保证,进入函数时,区间[beg, end - 1)内的元素原本便已经是一个heap,而新元素紧跟其后。
pop_heap
void pop_heap(RandomAccessIterator beg, RandomAccessIterator end); void pop_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op);
- 以上两种形式都是将heap[beg, end)内的最高元素,即第一个元素,移到最后位置。并将剩余区间[beg, end -1)内的元素组织起来,成为一个新的heap。
- op是个可以选的二元判断式,被当做排序准则:op(elem1, elem2).
- 调用者必须保证,进入函数时,区间[beg, end)内的元素原本便已经形成一个heap.
sort_heap
void sort_heap(RandomAccessIterator beg, RandomAccessIterator end); void sort_heap(RandomAccessIterator beg, RandomAccessIterator end, BinaryPredicate op);
- 以上两种形式都是可以将heap[beg, end)转换为一个已序(sorted)序列
- op是个二元判断式,被视为排序准则:op(elem1, elem2)
- 调用者必须保证,进入函数时,区间[beg, end)内的元素原本便已经形成一个heap
- 此算法一旦执行结束,该区间就不再是个heap了。
heap算法使用范例
/**************************************************************** *函数名称:HeapTest *功 能:Heap算法使用实例 *作 者:Jin *日 期:2016年7月5日 ****************************************************************/ void HeapTest() { vector<int> nVector; InsertElements(nVector, 3, 7); InsertElements(nVector, 5, 9); InsertElements(nVector, 1, 4); PrintElements(nVector, "on entry: "); //convert collection into heap make_heap(nVector.begin(), nVector.end()); PrintElements(nVector, "after make_heap: "); //pop next element out of heap pop_heap(nVector.begin(), nVector.end()); nVector.pop_back(); PrintElements(nVector, "after pop_heap(): "); //push new element into the heap nVector.push_back(17); push_heap(nVector.begin(), nVector.end()); PrintElements(nVector, "after push_heap(): "); // convert heap into a sorted collection // Note: after the call it is no longer a heap sort_heap(nVector.begin(), nVector.end()); PrintElements(nVector, "after sort_heap(): "); }输出结果:
从上面可知,调用了make_heap之后区间内的元素就变成堆元素了,将其转换为二叉树形式如图1,将会发现每个父节点都会大于子节点。push_heap()和pop_heap()虽然会替换元素,但二叉树的性质保持不变(每个子节点不会大于其父节点)。
图1 二叉树