http://www.cplusplus.com/reference/algorithm/push_heap/
这太令人困惑了。要在std中使用堆,首先将元素放在向量中,然后调用
std::make_heap(v.begin(), v.end());
如果我在向量中插入元素怎么办?堆乱了吗?例如,v最初可能有10个元素,我只将堆从第3个元素到第7个元素,现在我将元素插入第5个和第9个位置,是不是在这个过程中销毁了堆结构?
为什么在再次致电push_back(99)
之前,您必须先在示例中push_heap
?看起来不仅令人困惑而且效率低下。
sort_heap()
的含义是什么?不应该对堆进行排序,(那是什么使它成为堆的权利?)
答案 0 :(得分:16)
首先:make_heap
,push_heap
,pop_heap
和sort_heap
主要是堆"原语","正常工作&# 34;你通常使用std::priority_queue
,它更直接使用(虽然它确实有一些其他的隐藏 - 即,无法直接访问底层容器而没有等同于sort_heap
)。
push_heap
和pop_heap
旨在处理通用迭代器确定的范围,并且与STL算法一样(例如参见各种std::remove_if
& co。),不能改变底层容器的大小(毕竟传递给它们的是几个迭代器)。
出于这个原因,push_heap
和pop_heap
不实际上会将一个元素添加到容器中,但只是修补范围内的顺序以包含新元素/删除顶部元素并返回相关范围" heap-property"。
push_heap
期望接收一个范围,使得[first,last-1)已经是一个堆(即它具有堆属性),并且要添加到堆中的元素存储在最后一个位置范围(即last-1
)。在push_heap
之后,整个范围[first,last]现在是一个堆,并添加了新元素。
这就是为什么在示例中 first 执行push_back
(使新元素准备好由push_heap
操纵),然后调用{{ 1}}。
相反,push_heap
将从作为堆的[first,last]范围开始,然后执行其操作,最后您将[first,last-1]作为堆,并在最后一个位置(即pop_heap
)从正确的堆范围中提取的最高元素。这就是为什么在*(last-1)
示例pop_heap
之后,将向量大小减小1,从而丢弃提取的值,将向量仅减少到堆的范围。< / p>
相反,使用
pop_back
是因为尽管堆使用特定排序来实现其性能特征,但它不会保持范围排序; sort_heap
通过对元素进行排序来破坏堆(即范围失去其堆属性)(排序利用堆属性,这可能比普通sort_heap
提供一些性能提升。)
答案 1 :(得分:3)
如果我在向量中插入元素怎么办?堆是否搞砸了?
是的,它可以。如果你在向量中推送一个新元素,你会得到一个新的向量,它可能不再是一个堆了。
为什么在再次调用push_heap之前,你必须先在示例中使用push_back(99)?看起来不仅令人困惑而且效率低下。
不,它效率不高。 std::vector::push_back
的复杂性几乎是不变的。真正的工作是由std::push_heap
完成的,其复杂度为“最多2×log(N)”。
请注意,std::make_heap
和std::push_heap
非常不同。第一个不假设容器的状态,第二个假设[begin, end-2)
中的元素已经是一个有效的堆(在push_back
的情况下使其更有效)。
sort_heap()的含义是什么?不应该对堆进行排序,(那是什么使它成为堆的权利?)
堆只有特定的属性,使其更容易排序,但它尚未排序。例如,这是堆:
它没有排序。
答案 2 :(得分:1)
我发现此文档不那么令人困惑:http://en.cppreference.com/w/cpp/algorithm#Heap_operations
如果使用std::push_heap()
,则会保留堆属性。
如果在向量中插入一个或多个元素,则必须调用std::make_heap()
来恢复堆属性。
sort_heap()的含义是什么? 不应该对堆进行排序,(那是什么使它成为一个堆?)
都能跟得上!你必须了解堆是什么。因此sort_heap()
将堆转换为一系列已排序的元素。