Heap算法详解

算法描述

就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 二叉树


posted @ 2016-07-06 21:28  小怪兽&奥特曼  阅读(302)  评论(0编辑  收藏  举报