[英]How make_heap() function works?
我对向量和迭代器有基本的了解。 但是我在理解以下代码片段的输出时遇到了问题。
具体来说,我无法找到 make_heap() 函数的功能。 它是如何产生输出的:91 67 41 24 59 32 23 13 !!
据我所知,堆看起来像这样:
91
/ \
67 41
/ \ / \
59 24 32 23
/
13
所以,我期待输出为:91 67 41 59 24 32 23 13
如果有人能帮助我理解 make_heap() 如何生成这样的输出,我将不胜感激。
int main()
{
int aI[] = { 13, 67, 32, 24, 59, 41, 23, 91 };
vector<int> v(aI, aI + 8);
make_heap( v.begin(), v.end() );
vector<int>::iterator it;
for( it = v.begin(); it != v.end(); ++it )
cout << *it << " ";
//Output: 91 67 41 24 59 32 23 13
return 0;
}
二叉堆必须满足两个约束(除了是二叉树):
二叉堆中兄弟节点的顺序不是由堆属性指定的,单个节点的两个子节点可以自由互换,除非这样做违反了形状属性。
因此,在您的示例中,您可以在第二级节点之间自由交换并获得多个均合法的输出。
make_heap
通过对元素重新排序以使其满足堆约束,从而在向量中构造一个二叉堆。 构造的堆是一个最大堆,也就是说,它将最大的(根据operator<
或提供的比较)元素放在第一个元素中,堆的根,它是向量的第一个元素。
二叉堆是一棵平衡二叉树,它满足父节点的值总是大于子节点的值(在这种情况下,更小更常见)的条件。 这意味着根总是包含最大的元素。 结合根的有效提取,这构成了一个很好的优先级队列。
二叉堆以广度优先的预序存储在数组中。 即根在位置 0,它是位置 1 和 2 的直接子代,位置 3 和 4 的 1 的子代,位置 5 和 6 的 2 的子代,依此类推。 通常,节点n
子节点位于2*n + 1
和2*n + 2
。
在 C++ 中, make_heap
函数与push_heap
和pop_heap
一起实现了一个完整的优先级队列超过向量。 还有priority_queue
容器包装器将它们组合在一个类中。
优先队列主要用于著名的 Dijkstra 算法和各种调度算法。 由于 Dijkstra 算法需要选择最小值,因此更常见的是在根中定义具有最小值的堆。 C ++标准库选择具有最大定义它,但请注意,您可以通过平凡赋予它得到最小堆greater_than
代替less_than
作为比较。
有两种方法可以构建堆。 通过将每个元素推向它,或者通过从元素的前半部分(后半部分是叶子)固定不变量。 后者效率更高,所以:
当堆化一个未排序的数组时,该算法利用这样的一面,即一半数组将是叶节点(数组中的较高索引),另一半将是这些叶节点的父节点。 该算法只需要遍历父节点并修复它们的逻辑子树。 叶节点作为有效的子堆开始,因为根据定义,它们大于它们不存在的子节点。
所以我们只需要修复至少有一个非叶子节点的子堆。 以正确的顺序(从数组的中间到最低索引)完成,当最后一个父节点被堆化时,整个数组将是一个有效的堆。
每个步骤如下所示:
iteration 1:
13 67 32 24 59 41 23 91
^ current parent under consideration
^ children of this parent
13 67 32 91 59 41 23 24 after heapifying this sub-tree
-- --
iteration 2:
13 67 32 91 59 41 23 24
^ current parent under consideration
^ ^ children of this parent
13 67 41 91 59 32 23 24 after heapifying this sub-tree
-- --
iteration 3:
13 67 41 91 59 32 23 24
^ current parent under consideration
^ ^ children of this parent
13 91 41 67 59 32 23 24 after heapifying this sub-tree
-- --
iteration 4:
13 91 41 67 59 32 23 24
^ current parent under consideration
^ ^ children of this parent
91 13 41 67 59 32 23 24 heapify swap 1
-- --
91 67 41 13 59 32 23 24 heapify swap 2
-- --
91 67 41 24 59 32 23 13 after heapifying this sub-tree
-- --
堆化数组的简单方法是遍历数组从索引0
到n-1
并在每次迭代时将该索引处的元素“添加”到由该索引之前的元素组成的堆中。 这将导致您期望的堆。 该算法导致n
堆化操作。 make_heap()
使用的算法导致n/2
堆化操作。 它导致不同但仍然有效的堆。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.