9 #ifndef WILDERFIELD_PRIORITY_MAP_HPP
10 #define WILDERFIELD_PRIORITY_MAP_HPP
12 #include <unordered_map>
14 #include <unordered_set>
17 #include <type_traits>
20 namespace wilderfield {
37 typename Compare = std::greater<ValType>,
38 typename Hash = std::hash<KeyType>
42 static_assert(std::is_arithmetic<ValType>::value,
"ValType must be a numeric type.");
47 std::list<ValType> vals_;
49 std::unordered_map<KeyType, typename std::list<ValType>::iterator, Hash> keys_;
51 std::unordered_map<ValType, std::unordered_set<KeyType>> valToKeys_;
56 void insert(
const KeyType& key,
const ValType& newVal);
60 void update(
const KeyType& key,
const ValType& newVal);
63 ValType getVal(
const KeyType& key)
const {
return *(keys_.at(key)); }
67 size_t size()
const {
return keys_.size(); }
69 bool empty()
const {
return keys_.empty(); }
71 size_t count(
const KeyType& key)
const {
return keys_.count(key); }
73 std::pair<KeyType, ValType>
top()
const;
75 size_t erase(
const KeyType& key);
80 Proxy operator[](
const KeyType& key);
92 pm->update(key, pm->getVal(key)+1);
97 Proxy operator++(
int) {
103 Proxy& operator--() {
104 pm->update(key, pm->getVal(key)-1);
108 Proxy operator--(
int) {
114 void operator=(
const ValType& val) {pm->update(key, val);}
116 operator ValType()
const {
return pm->getVal(key);}
130 if (keys_.find(key) != keys_.end()) {
131 auto oldIt = keys_[key];
132 valToKeys_[*oldIt].erase(key);
133 if (valToKeys_[*oldIt].empty()) {
134 valToKeys_.erase(*oldIt);
138 return keys_.erase(key);
149 throw std::out_of_range(
"Can't access top on an empty priority_map.");
151 const auto val = vals_.front();
152 if (valToKeys_.at(val).empty()) {
153 throw std::logic_error(
"Inconsistent state: Val with no keys.");
156 return {*(valToKeys_.at(val).begin()), val};
167 throw std::out_of_range(
"Can't pop from empty priority_map.");
170 auto oldIt = vals_.begin();
171 if (valToKeys_[*oldIt].empty()) {
172 throw std::logic_error(
"Inconsistent state: Val with no keys.");
174 KeyType key = *(valToKeys_[*oldIt].begin());
176 valToKeys_[*oldIt].erase(key);
180 if (valToKeys_[*oldIt].empty()) {
181 valToKeys_.erase(*oldIt);
194 if (keys_.find(key) == keys_.end()) {
196 valToKeys_[0].insert(key);
202 auto insertionPoint = std::find_if(vals_.begin(), vals_.end(),
203 [&](
const auto val) {
207 if (insertionPoint == vals_.end() || (*insertionPoint) != 0) {
208 insertionPoint = vals_.insert(insertionPoint, 0);
211 keys_[key] = insertionPoint;
218 auto insertionPoint = std::find_if(vals_.rbegin(), vals_.rend(),
219 [&](
const auto val) {
223 if (insertionPoint == vals_.rend() || (*insertionPoint) != 0) {
224 auto newIt = vals_.insert(insertionPoint.base(), 0);
228 keys_[key] = std::next(insertionPoint).base();
244 void priority_map<KeyType, ValType, Compare, Hash>::update(
const KeyType& key,
const ValType& newVal) {
246 auto oldIt = keys_[key];
249 ValType oldVal = *oldIt;
251 if (oldVal == newVal)
return;
255 valToKeys_[oldVal].erase(key);
258 valToKeys_[newVal].insert(key);
261 if (comp_(oldVal, newVal)) {
264 auto insertionPoint = std::find_if(oldIt, vals_.end(),
265 [&](
const auto val) {
267 return val <= newVal;
269 return val >= newVal;
272 if (insertionPoint == vals_.end() || (*insertionPoint) != newVal) {
273 insertionPoint = vals_.insert(insertionPoint, newVal);
276 keys_[key] = insertionPoint;
282 typename std::list<ValType>::reverse_iterator oldRit(oldIt);
285 auto insertionPoint = std::find_if(oldRit, vals_.rend(),
286 [&](
const auto val) {
288 return val <= newVal;
290 return val >= newVal;
293 if (insertionPoint == vals_.rend() || (*insertionPoint) != newVal) {
294 auto newIt = vals_.insert(insertionPoint.base(), newVal);
296 keys_[key] = std::next(insertionPoint).base();
299 keys_[key] = std::next(insertionPoint).base();
304 if (valToKeys_[oldVal].empty()) {
305 valToKeys_.erase(*oldIt);
317 typename priority_map<KeyType, ValType, Compare, Hash>::Proxy priority_map<KeyType, ValType, Compare, Hash>::operator[](
const KeyType& key) {
320 if (keys_.find(key) == keys_.end()) {
323 return Proxy(
this, key);
Definition: priority_map.hpp:83
Priority map class.
Definition: priority_map.hpp:40
bool empty() const
Checks whether the priority map is empty.
Definition: priority_map.hpp:69
size_t count(const KeyType &key) const
Returns the count of a particular key in the map.
Definition: priority_map.hpp:71
void pop()
Removes the top element from the priority map.
Definition: priority_map.hpp:165
std::pair< KeyType, ValType > top() const
Returns the top element (key-value pair) in the priority map.
Definition: priority_map.hpp:147
size_t erase(const KeyType &key)
Erases key from the priority map. Returns the number of elements removed (0 or 1).
Definition: priority_map.hpp:129
size_t size() const
Returns the number of unique keys in the priority map.
Definition: priority_map.hpp:67