#pragma once #include #include "Array.h" namespace Framework { template 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 friend class HashMap; }; template class MapIterator { private: int bucketIndex; Iterator> iterator; Array>** buckets; int bucketCount; public: MapIterator(Array>** buckets, int bucketCount, int bucketIndex, Iterator> iterator) : iterator(iterator) { while (bucketIndex < bucketCount && (!buckets[bucketIndex] || buckets[bucketIndex]->getEintragAnzahl() == 0)) { bucketIndex++; iterator = Iterator>(0, 0); } if (bucketIndex < bucketCount) { if (!iterator) this->iterator = buckets[bucketIndex]->begin(); } else { this->iterator = Iterator>(0, 0); this->bucketIndex = 0; this->buckets = 0; this->bucketCount = 0; return; } this->buckets = buckets; this->bucketCount = bucketCount; this->bucketIndex = bucketIndex; } MapIterator(const MapIterator& it) : iterator(it.iterator) { buckets = it.buckets; bucketCount = it.bucketCount; bucketIndex = it.bucketIndex; } MapIterator& operator=(MapIterator 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 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, Iterator>(0, 0)); } operator bool() { return bucketIndex < bucketCount; } operator MapEntry() { 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& 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 = Iterator>(0, 0); this->bucketIndex = 0; this->buckets = 0; this->bucketCount = 0; } } return *this; } MapIterator operator++(int) //! postfix { MapIterator temp(*this); ++(*this); return temp; } MapEntry 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 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 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& r) { return buckets != r.buckets || iterator != r.iterator; } }; template class HashMap : public virtual ReferenceCounter { private: Array>** buckets; int bucketCount; std::function hash; int size; public: HashMap(int bucketCount, std::function hash) : ReferenceCounter(), buckets(new Array>*[bucketCount]), bucketCount(bucketCount), hash(hash), size(0) { memset(buckets, 0, sizeof(Array>*) * 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>(); for (auto iterator = buckets[index]->begin(); iterator; iterator++) { if (iterator._.getKey() == key) { iterator.set(MapEntry(key, value)); return; } } buckets[index]->add(MapEntry(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 begin() { return MapIterator( buckets, bucketCount, 0, Iterator>(0, 0)); } MapIterator end() { return MapIterator(0, 0, 0, Iterator>(0, 0)); } }; } // namespace Framework