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:
parent
b501738e7d
commit
1448acd98a
@ -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)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user