|
@@ -61,6 +61,8 @@ struct HashMapElement {
|
|
data(p_key, p_value) {}
|
|
data(p_key, p_value) {}
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+bool _hashmap_variant_less_than(const Variant &p_left, const Variant &p_right);
|
|
|
|
+
|
|
template <typename TKey, typename TValue,
|
|
template <typename TKey, typename TValue,
|
|
typename Hasher = HashMapHasherDefault,
|
|
typename Hasher = HashMapHasherDefault,
|
|
typename Comparator = HashMapComparatorDefault<TKey>,
|
|
typename Comparator = HashMapComparatorDefault<TKey>,
|
|
@@ -271,6 +273,47 @@ public:
|
|
num_elements = 0;
|
|
num_elements = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ void sort() {
|
|
|
|
+ if (elements == nullptr || num_elements < 2) {
|
|
|
|
+ return; // An empty or single element HashMap is already sorted.
|
|
|
|
+ }
|
|
|
|
+ // Use insertion sort because we want this operation to be fast for the
|
|
|
|
+ // common case where the input is already sorted or nearly sorted.
|
|
|
|
+ HashMapElement<TKey, TValue> *inserting = head_element->next;
|
|
|
|
+ while (inserting != nullptr) {
|
|
|
|
+ HashMapElement<TKey, TValue> *after = nullptr;
|
|
|
|
+ for (HashMapElement<TKey, TValue> *current = inserting->prev; current != nullptr; current = current->prev) {
|
|
|
|
+ if (_hashmap_variant_less_than(inserting->data.key, current->data.key)) {
|
|
|
|
+ after = current;
|
|
|
|
+ } else {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ HashMapElement<TKey, TValue> *next = inserting->next;
|
|
|
|
+ if (after != nullptr) {
|
|
|
|
+ // Modify the elements around `inserting` to remove it from its current position.
|
|
|
|
+ inserting->prev->next = next;
|
|
|
|
+ if (next == nullptr) {
|
|
|
|
+ tail_element = inserting->prev;
|
|
|
|
+ } else {
|
|
|
|
+ next->prev = inserting->prev;
|
|
|
|
+ }
|
|
|
|
+ // Modify `before` and `after` to insert `inserting` between them.
|
|
|
|
+ HashMapElement<TKey, TValue> *before = after->prev;
|
|
|
|
+ if (before == nullptr) {
|
|
|
|
+ head_element = inserting;
|
|
|
|
+ } else {
|
|
|
|
+ before->next = inserting;
|
|
|
|
+ }
|
|
|
|
+ after->prev = inserting;
|
|
|
|
+ // Point `inserting` to its new surroundings.
|
|
|
|
+ inserting->prev = before;
|
|
|
|
+ inserting->next = after;
|
|
|
|
+ }
|
|
|
|
+ inserting = next;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
TValue &get(const TKey &p_key) {
|
|
TValue &get(const TKey &p_key) {
|
|
uint32_t pos = 0;
|
|
uint32_t pos = 0;
|
|
bool exists = _lookup_pos(p_key, pos);
|
|
bool exists = _lookup_pos(p_key, pos);
|