#pragma once #include <functional> #include "Array.h" namespace Framework { template<typename K, typename V> class MapEntry { private: K key; V value; public: MapEntry() {} MapEntry(K key, V value) : key(key), value(value) {} K getKey() { return key; } V getValue() { return value; } template<typename K2, typename V2> friend class HashMap; }; template<typename K, typename V> class MapIterator { private: int bucketIndex; ArrayIterator<MapEntry<K, V>> iterator; Array<MapEntry<K, V>>** buckets; int bucketCount; public: MapIterator(Array<MapEntry<K, V>>** buckets, int bucketCount, int bucketIndex, ArrayIterator<MapEntry<K, V>> iterator) : iterator(iterator) { while (bucketIndex < bucketCount && (!buckets[bucketIndex] || buckets[bucketIndex]->getEintragAnzahl() == 0)) { bucketIndex++; iterator = ArrayIterator<MapEntry<K, V>>(0, 0); } if (bucketIndex < bucketCount) { if (!iterator) this->iterator = buckets[bucketIndex]->begin(); } else { this->iterator = ArrayIterator<MapEntry<K, V>>(0, 0); this->bucketIndex = 0; this->buckets = 0; this->bucketCount = 0; return; } this->buckets = buckets; this->bucketCount = bucketCount; this->bucketIndex = bucketIndex; } MapIterator(const MapIterator<K, V>& it) : iterator(it.iterator) { buckets = it.buckets; bucketCount = it.bucketCount; bucketIndex = it.bucketIndex; } MapIterator<K, V>& operator=(MapIterator<K, V> r) { iterator = r.iterator; buckets = r.buckets; bucketCount = r.bucketCount; bucketIndex = r.bucketIndex; return *this; } bool hasNext() { if (iterator && iterator.hasNext()) return 1; int ind = bucketIndex + 1; while (ind < bucketCount && (!buckets[ind] || buckets[ind]->getEintragAnzahl() == 0)) ind++; return ind < bucketCount; } MapIterator<K, V> next() { if (bucketIndex >= bucketCount) { Text err = "Index out of Range Exception File: "; err += __FILE__; err += " Line: "; err += __LINE__; throw std::out_of_range(err); } if (iterator.hasNext()) return MapIterator( buckets, bucketCount, bucketIndex, iterator.next()); else return MapIterator(buckets, bucketCount, bucketIndex + 1, ArrayIterator<MapEntry<K, V>>(0, 0)); } operator bool() { return bucketIndex < bucketCount; } operator MapEntry<K, V>() { if (bucketIndex >= bucketCount) { Text err = "Index out of Range Exception File: "; err += __FILE__; err += " Line: "; err += __LINE__; throw std::out_of_range(err); } return iterator.val(); } MapIterator<K, V>& operator++() //! prefix { ++iterator; if (!iterator) { bucketIndex++; while (bucketIndex < bucketCount && (!buckets[bucketIndex] || buckets[bucketIndex]->getEintragAnzahl() == 0)) bucketIndex++; if (bucketIndex < bucketCount) this->iterator = buckets[bucketIndex]->begin(); else { this->iterator = ArrayIterator<MapEntry<K, V>>(0, 0); this->bucketIndex = 0; this->buckets = 0; this->bucketCount = 0; } } return *this; } MapIterator<K, V> operator++(int) //! postfix { MapIterator<K, V> temp(*this); ++(*this); return temp; } MapEntry<K, V> operator*() { if (bucketIndex >= bucketCount) { Text err = "Index out of Range Exception File: "; err += __FILE__; err += " Line: "; err += __LINE__; throw std::out_of_range(err); } return iterator.val(); } MapEntry<K, V> operator->() { if (bucketIndex >= bucketCount) { Text err = "Index out of Range Exception File: "; err += __FILE__; err += " Line: "; err += __LINE__; throw std::out_of_range(err); } return iterator.val(); } void set(MapEntry<K, V> val) { if (bucketIndex < bucketCount) iterator.set(val); else { Text err = "Index out of Range Exception File: "; err += __FILE__; err += " Line: "; err += __LINE__; throw std::out_of_range(err); } } bool operator!=(MapIterator<K, V>& r) { return buckets != r.buckets || iterator != r.iterator; } }; template<typename K, typename V> class HashMap : public virtual ReferenceCounter { private: Array<MapEntry<K, V>>** buckets; int bucketCount; std::function<int(K)> hash; int size; public: HashMap(int bucketCount, std::function<int(K)> hash) : ReferenceCounter(), buckets(new Array<MapEntry<K, V>>*[bucketCount]), bucketCount(bucketCount), hash(hash), size(0) { memset(buckets, 0, sizeof(Array<MapEntry<K, V>>*) * bucketCount); } ~HashMap() { for (int i = 0; i < bucketCount; i++) { if (buckets[i]) buckets[i]->release(); } delete[] buckets; } void put(K key, V value) { int index = abs(hash(key)) % bucketCount; if (!buckets[index]) buckets[index] = new Array<MapEntry<K, V>>(); for (auto iterator = buckets[index]->begin(); iterator; iterator++) { if (iterator._.getKey() == key) { iterator.set(MapEntry<K, V>(key, value)); return; } } buckets[index]->add(MapEntry<K, V>(key, value)); size++; } void remove(K key) { int index = abs(hash(key)) % bucketCount; if (!buckets[index]) return; int listIndex = 0; for (auto bucket : *buckets[index]) { if (bucket.getKey() == key) { buckets[index]->remove(listIndex); size--; return; } listIndex++; } } V get(K key) const { int index = abs(hash(key)) % bucketCount; if (!buckets[index]) throw "element not found"; for (auto iterator : *buckets[index]) { if (iterator.getKey() == key) return iterator.getValue(); } throw "element not found"; } V safeGet(K key, V fallback) const { int index = abs(hash(key)) % bucketCount; if (!buckets[index]) return fallback; for (auto bucket : *buckets[index]) { if (bucket.getKey() == key) return bucket.getValue(); } return fallback; } bool has(K key) const { int index = abs(hash(key)) % bucketCount; if (!buckets[index]) return 0; for (auto bucket : *buckets[index]) { if (bucket.getKey() == key) return 1; } return 0; } int getSize() const { return size; } void leeren() { for (int i = 0; i < bucketCount; i++) { if (buckets[i]) buckets[i]->leeren(); } } MapIterator<K, V> begin() { return MapIterator<K, V>( buckets, bucketCount, 0, ArrayIterator<MapEntry<K, V>>(0, 0)); } MapIterator<K, V> end() { return MapIterator<K, V>( 0, 0, 0, ArrayIterator<MapEntry<K, V>>(0, 0)); } }; } // namespace Framework