When inserting a new element in the heap, we don't need

std::push_heap and a std::pop_heap

We can implement that using a single std::pop_heap.  This reduces the max number
of comparisons for each PushInternal() from

log n (for push_heap) + 2 * log n (for pop_heap) = 3 * log n

to

2 * log n (i.e., 33% reduction).  For more info, see

https://en.cppreference.com/w/cpp/algorithm/push_heap
https://en.cppreference.com/w/cpp/algorithm/pop_heap

PiperOrigin-RevId: 263805637
This commit is contained in:
A. Unique TensorFlower 2019-08-16 11:02:48 -07:00 committed by TensorFlower Gardener
parent b501738e7d
commit 1448acd98a

View File

@ -235,10 +235,18 @@ void TopN<T, Cmp>::PushInternal(U &&v, T *dropped) { // NOLINT(build/c++11)
} else {
// Only insert the new element if it is greater than the least element.
if (cmp_(v, elements_.front())) {
// Store new element in the last slot of elements_. Remember from the
// comments on elements_ that this last slot is unused, so we don't
// overwrite anything useful.
elements_.back() = std::forward<U>(v); // NOLINT(build/c++11)
std::push_heap(elements_.begin(), elements_.end(), cmp_);
if (dropped) *dropped = std::move(elements_.front());
// stp::pop_heap() swaps elements_.front() and elements_.back() and
// rearranges elements from [elements_.begin(), elements_.end() - 1) such
// that they are a heap according to cmp_. Net effect: remove
// elements_.front() from the heap, and add the new element instead. For
// more info, see https://en.cppreference.com/w/cpp/algorithm/pop_heap.
std::pop_heap(elements_.begin(), elements_.end(), cmp_);
if (dropped) *dropped = std::move(elements_.back());
} else {
if (dropped) *dropped = std::forward<U>(v); // NOLINT(build/c++11)
}