c++中的Heap算法

本文详细介绍了C++中的堆排序算法,包括make_heap()、push_heap()、pop_heap()和sort_heap()四个核心函数的用途和复杂度。堆可以视为一种特殊的二叉树结构,用于实现优先队列。通过实例演示了如何使用这些函数进行元素操作,最后展示了堆排序的过程及其转换成有序序列的结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

就排序而言,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()虽然会替换元素,但是二叉树结构的恒常性质不变。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值