blob: 860f782c5e0e77cac80d98e99992a8bd22349bcb [file] [log] [blame] [edit]
// Copyright 2017-2020 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef VERIBLE_COMMON_UTIL_TOP_N_H_
#define VERIBLE_COMMON_UTIL_TOP_N_H_
#include <functional> // for std::greater
#include <queue> // for std::priority_queue
#include <vector>
namespace verible {
// Maintains a collection of best N elements, as determined by a comparator.
// This class exists as a drop-in replacement for a similar library,
// and provides a subset of the original class's methods and interfaces.
//
// This priority-queue based implementation is NOT optimized;
// its performance does not matter at this time.
template <typename T, typename Comp = std::greater<T>>
class TopN {
public:
typedef T value_type;
explicit TopN(size_t limit) : max_size_(limit) {}
// Capacity.
size_t max_size() const { return max_size_; }
// Current number of elements, always <= max_size().
size_t size() const { return elements_.size(); }
bool empty() const { return size() == 0; }
// TODO(fangism): void reserve(size_t n);
// Inserts an element in the prescribed sorted order, and caps the size (K).
// Has same run-time as heap-insertion, no worse than O(lg K) ~ O(1).
// Removing the worst element is a heap-remove-min-key, which is O(1).
void push(const value_type& v) {
elements_.push(v);
if (size() > max_size()) {
elements_.pop(); // remove worst element
}
}
// TODO(fangism): bottom(): the next element to fall off the end, if replaced.
// const value_type& bottom() const;
// Returns a copy of elements ordered best-to-worst. (nondestructive)
std::vector<value_type> Take() const {
// Copying a priority_queue only to pluck out its elements
// destructively is inefficient.
// TODO(fangism): if desired, make a destructive variant that avoids copy
// TODO(fangism): re-implement using direct heap operations on array
impl_type copy(elements_);
// vector(size) constructor requires default constructibility
std::vector<value_type> result(size());
auto iter = result.rbegin(); // the first value is the worst, last is best
while (!copy.empty()) {
*iter++ = copy.top();
copy.pop();
}
return result;
}
private:
// Maximum number of best elements to retain.
size_t max_size_;
// For simplicity, use existing priority_queue internally, which implements
// the desired ordering.
typedef std::priority_queue<T, std::vector<T>, Comp> impl_type;
// Internal storage of elements.
impl_type elements_;
// Comparator (same as that used in the elements_ container)
Comp comp_;
};
} // namespace verible
#endif // VERIBLE_COMMON_UTIL_TOP_N_H_