就排序而言,heap是一种特别的元素组织方式,应用与heap排序。heap课被视为一个以序列式群集实作而成的二叉树,具有两大性质
1.第一个元素总是最大。
2.总是能够在对数时间内增加或者移除一个元素。
heap是实作proority queue的一个理想结构,因此,heap算法也在priority_queue容器中有所应用吗,为了处理heap,stl提供了四种算法。
1.make_heap() 将某区间内的元素转化为heap
2.push_heap() 对着heap增加一个元素
3.pop_heap() 对着heap取出一个元素
4.sort_heap() 将heap转化为一个以序集群(此后就不在是heap了)
就像以前的情况一样,你可以传递一个二元判断式作为排序准则。缺省的排序准则是operator<。
heap算法细节
void make_heap(RandomAccessIterator beg , RandomAccessIterator end)
void make_heap(RandomAccessIterator beg , RandomAccessIterator end , BinaryPredicate op)
两种形式都将区间(beg,end)内的元素转化为heap。
op是一个可有可无的二元判断式,被视为是排序准则:op(elem1 , elem2)
只有在多于一个元素的情况系啊,才有必要使用这些函数来处理heap,如果只有单一元素,那么他自动就形成一个heap
复杂度: 线性,最多执行3*numberOfElements 次比较
void push_heap(RandomAccessIterator beg , RandomAccessIterator end)
void push_heap(RandomAccessIterator beg , RandomAccessIterator end, BinaryPredicate op)
两种形式豆浆end之前的最后一个元素假如原本就是个heap的[beg , end -1]区间内,使整个区间成为一个heap
op是一个可有可无的二元判断式,被视为是排序准则:op(elem1 , elem2)
调用者必须保证,进入函数时,区间[beg , end - 1]内的元素原来便形成一个heap , 新元素紧跟其后
复杂度:对数, 最多执行log(numberOfElements)次比较操作
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
复杂度: 对数, 最多执行 2* log(numberOfEments)次比较操作
void sort_heap(RandomAccessIterator beg , RandomAccessIterator end)
void sort_heap(RandomAccessIterator beg , RandomAccessIterator end, BinaryPredicate op)
以上两种形式都可以将heap[beg , end]转化为一个已序序列。
op是一个可有可无的二元判断式,被视为是排序准则:op(elem1 , elem2)
注意, 此算法一结束就不再是一个heap了
调用者必须要争,进入函数时, 区间内的元素原来便已形成一个heap
复杂度: n-log-n ,最多执行numberOfElement * log(numberOfElements)次比较动作
heap算法实例:
#include"algo.h"
#include<cstdlib>
using namespace std;
int main()
{
vector<int> coll;
INSERT_Element(coll, 3, 7);
INSERT_Element(coll, 5, 9);
INSERT_Element(coll, 1, 4);
Print_Element(coll);
make_heap(coll.begin(), coll.end());
Print_Element(coll, "after make_heap():");
pop_heap(coll.begin(), coll.end());
coll.pop_back();
Print_Element(coll, "after pop_heap():");
coll.push_back(7);
push_heap(coll.begin(), coll.end());
Print_Element(coll, "after push_heap():");
sort_heap(coll.begin(), coll.end());
Print_Element(coll, "after sort_heap():");
getchar();
getchar();
}
调用make_heap()后,元素被排序为堆:
3 4 5 6 7 5 6 7 8 9 1 2 3 4
after make_heap():9 8 6 7 7 5 5 3 6 4 1 2 3 4
after pop_heap():8 7 6 7 4 5 5 3 6 4 1 2 3
after push_heap():8 7 7 7 4 5 6 3 6 4 1 2 3 5
after sort_heap():1 2 3 3 4 4 5 5 6 6 7 7 7 8
如果把这些元素转化为二叉树结构,你会发现每个节点的值都小于或者等于其父节点的值。push_heap(), pop_heap()虽然会替换元素,但是二叉树结构的恒常性质不变。