如何使用std :: make_heap

时间:2014-05-07 22:49:49

标签: c++ heap std

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()的含义是什么?不应该对堆进行排序,(那是什么使它成为堆的权利?)

3 个答案:

答案 0 :(得分:16)

首先:make_heappush_heappop_heapsort_heap主要是堆"原语","正常工作&# 34;你通常使用std::priority_queue,它更直接使用(虽然它确实有一些其他的隐藏 - 即,无法直接访问底层容器而没有等同于sort_heap)。


push_heappop_heap旨在处理通用迭代器确定的范围,并且与STL算法一样(例如参见各种std::remove_if& co。),不能改变底层容器的大小(毕竟传递给它们的是几个迭代器)。

出于这个原因,push_heappop_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_heapstd::push_heap非常不同。第一个不假设容器的状态,第二个假设[begin, end-2)中的元素已经是一个有效的堆(在push_back的情况下使其更有效)。

  

sort_heap()的含义是什么?不应该对堆进行排序,(那是什么使它成为堆的权利?)

堆只有特定的属性,使其更容易排序,但它尚未排序。例如,这是

enter image description here

它没有排序。

答案 2 :(得分:1)

我发现此文档不那么令人困惑:http://en.cppreference.com/w/cpp/algorithm#Heap_operations

如果使用std::push_heap(),则会保留堆属性。

如果在向量中插入一个或多个元素,则必须调用std::make_heap()来恢复堆属性。

  

sort_heap()的含义是什么?   不应该对堆进行排序,(那是什么使它成为一个堆?)

都能跟得上!你必须了解堆是什么。因此sort_heap()将堆转换为一系列已排序的元素。