在最小堆中查找最大元素
Finding max element in min heap
我有一个最小堆:
std::vector<int> h;
...
std::make_heap(h.begin(), h.end(), std::greater<int>());
在大多数情况下,我需要最小堆操作std::push_heap
和std::pop_heap
,但在极少数情况下,我需要在最小堆中找到最大元素。我可以用std::max_element
做到这一点:
std::max_element(h.begin(), h.end());
但是,这必须扫描所有堆元素。
标准库是否提供了更有效的算法来查找最小堆中的 max 元素?
TL;DR在最小堆中,最大元素位于叶节点X中。因此,您可以将搜索限制为堆的大约一半元素,即,通过将最大元素的搜索限制为仅叶节点:
auto max_it = std::max_element(first_leaf_it, h.end());
请注意,这仍然需要线性时间,但常数因子比扫描所有元素要低,大约一半。
下面是一个类似 STL 的算法实现,用于在迭代器对提供的最小堆中查找最大元素:
template<typename RandomIt>
auto min_heap_max_element(RandomIt first, RandomIt last) {
auto n = last - first;
if (n < 2)
return first;
auto first_leaf_it = first + (n - 2) / 2 + 1;
return std::max_element(first_leaf_it, last);
}
要将其与您的示例一起使用:
auto max_it = min_heap_max_element(h.begin(), h.end());
如何查找堆中的第一个叶节点
堆的最后一个元素 -h.end()
指向的元素 - 显然是一个叶节点,它的父节点是最后一个非叶节点,因为如果这个节点后面有一个非叶节点,我们假设是堆的最后一个元素的元素不会是最后一个元素,这是一个矛盾。
因此,第一个叶节点将是紧跟在最后一个节点的父节点之后的元素。
您可以轻松找出最后一个节点的父节点在哪里:给定 i 堆元素的索引,其父节点位于索引(i - 1(/2处。因此,最后一个非叶节点的索引是(h.size() - 2) / 2
,因此第一个叶节点的索引是(h.size() - 2) / 2 + 1
。
X让我们假设最小堆中的最大元素位于非叶节点中。这意味着它至少有一个子节点。由于min-heap 属性,此子节点必须大于或等于其父节点。如果子节点大于其父节点(即最大元素(,则子节点大于最大值。这是不可能的,因为我们有矛盾。因此,它的所有子节点也必须是最大值,对于这些子节点也是如此。因此,如果最大值在堆中重复,或者唯一的最大值必须对应于叶节点,则最终会在其中一个叶节点中存在最大值。
如果您确实需要更好的(即亚线性(时间复杂度,请考虑使用最小-最大堆。此树中的任何节点都遵循以下属性:
当一个值处于偶数水平时,那么它是其后代中最大的。
当一个值处于奇数水平时,那么它是其后代中最少的。
因此,根具有最小值,其两个子项中的一个具有最大值。
插入/提取操作的时间复杂度与最小堆相同。
检查是否有C++最小堆实现?
- 使用堆查找第K个最大元素的时间复杂性
- 查找矩阵C++中每一列和每一行的最小和最大元素
- C++如何在向量中查找最常见的元素
- 查找两个排序向量中共有的元素
- 在对向量中查找元素的索引
- 查找数组中第一个最小值和最后一个最大值元素之间的算术平均值
- 查找矩阵中单元格的相邻元素
- 为什么使用数组元素查找最大数字的程序不起作用?
- 查找第一个数组中不存在的元素
- 查找最小的下一个更大的元素
- 在最小堆中查找最大元素
- 在向量中查找大于 0(或通常为 k)的最小元素的最佳方法是什么?
- set::find 查找不存在的元素
- 在集合中查找使用结构C++的元素
- 从斐波那契序列 c++ 中的数组中查找正确的元素时出错
- 用于查找数组中最大元素的出现次数的代码,给出分段错误
- 查找数组中指示性较大但数组中值较小的元素
- C++结构集无法按元素查找/擦除
- 如何在OpenCV中使用Matlab的512元素查找表数组?
- 使用数组的元素查找总和'k'