最近我在这里发布了一个关于stackoverflow多图时间复杂度问题的问题 我得到了一些很好的答案,这些答案让我提到了堆的使用,奇怪的是我以前根本没有使用过。我创建了一个使用 minheap 和 maxheap 重写的新程序。它工作得很好,因为它比我为这个问题实施的任何其他程序都要快得多。唯一的问题是它偶尔会抛出一些错误的答案。我回去做了很多调试。我意识到问题出在堆的组织上。它没有像我认为的那样使用 push_heap 和带有比较操作的 pop_heap 进行排序和分发。此外,当我尝试在 Visual Studio 上运行该程序时,我最终会看到很多断言错误被抛出。我尝试在 cplusplus.com 和 cppreference.com 上阅读更多关于堆及其方法的信息。
让我困惑的第一件事是push_heap。我理解它的方式是这样的:push_heap 有两个参数,默认情况下它将最小值推送到位置 last-1。只有当第一个参数小于第二个参数时它才会这样做,否则它保持不变。它基本上保持了正常堆的顺序。第三个可选参数是一个比较运算符,它可以用作greater(),然后将较大的元素推到最后一个位置。
没有意义的是,如果我在向量中动态插入或删除数字,我会在保持此顺序时遇到问题。如果我希望向量按升序排列,我将使用更大的操作来继续推动堆,以便值升序。但是当您第一次查看 push_heap 方法时会感到困惑,因为它看起来很像其他一些算法函数,它们在一系列数字中执行,例如:
std::unique (myvector.begin(), myvector.end(), myfunction);
push_heap 没有。它不会对向量范围内的所有数字进行这种比较操作,这点我一开始并不理解。
在发现 push_heap 并没有真正保持我的向量排序后,我必须保持我的向量排序才能使用二进制搜索。我使用了 sort_heap,但这会减慢程序速度,使其速度不够快。
另外,我发现有时 push_heap 在奇怪的情况下会抛出一个无效的堆错误。
例如:
push_heap(v.begin(), v.end(), greater<int>());
向量为755, 98, 55, 22
你会在 push_heap 之后看到:
22, 98, 55, 755
但是假设你有 22, 98, 55,755
由于比较的错误回报,通常它会继续前进而不执行任何推送。这是可以预料的。
但有时我会尝试 push_heap:
887、52、44、22
它会说
'invalid heap'
或者如果我尝试: 22, 52, 44, 887,而不是仅仅返回 false 并继续前进,它将与
'invalid heap'
pop_heap 有时也会发生这种情况。
为什么我得到无效堆?是因为所有堆都必须按降序排列吗?
编辑:我在 cplusplus.com 上找到了这个,我猜它回答了一个问题:
The element with the highest value is always pointed by first. The order of the other elements depends on the particular implementation, but it is consistent throughout all heap-related functions of this header.