算法描述
就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 二叉树