| // 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_ |