diff --git a/YASI_12/ds.HopScotchHashTable.h b/YASI_12/ds.HopScotchHashTable.h index e0b9d22..b1ab8c7 100644 --- a/YASI_12/ds.HopScotchHashTable.h +++ b/YASI_12/ds.HopScotchHashTable.h @@ -66,27 +66,30 @@ class HopScotchHashTable base; - virtual void copyTable(BucketType* oldTable, const unsigned int oldSize) override{ - base::copyTable(oldTable, oldSize); - } - - // swap two bucket entries - void swap(const int bucketOne, const int bucketTwo) const{ - EntryType temp = table[bucketOne]; - table[bucketOne] = table[bucketTwo]; - table[bucketTwo] = temp; - } - //---------- HopScotch Properties/Methods ---------- static const unsigned int INIT_H = 4; size_t H; // the neighborhood size size_t _zeroKeyBucket; // the bucket containing (hashed) zero key - // we should find something within first H-1 trials - // if not found, returns NULL - BucketType* lookupRight(const int bucket, const Key& key){ +#if _DEBUG + int _numHops; +#endif // _DEBUG + +public: + + virtual ~HopScotchHashTable(){} + HopScotchHashTable(unsigned int logSize = INIT_LOGSIZE, unsigned int H = INIT_H) :H(H), IntLinearProbingHashTable(logSize){ + assert(_size >= H); +#if _DEBUG + _numHops = 0; +#endif } + +protected: + + // we should find something within first H-1 trials + // if not found, returns NULL #if YASI_ALLOW_ZERO_KEY virtual inline bool isNull(const int bucket) const{ if (table[bucket].key != 0){ @@ -113,6 +116,18 @@ class HopScotchHashTable } #endif // YASI_ALLOW_ZERO_KEY + + virtual void copyTable(BucketType* oldTable, const unsigned int oldSize) override{ + base::copyTable(oldTable, oldSize); + } + + // swap two bucket entries + void swap(const int bucketOne, const int bucketTwo) const{ + EntryType temp = table[bucketOne]; + table[bucketOne] = table[bucketTwo]; + table[bucketTwo] = temp; + } + // push this entry to the right // returns false if it is not possible to push // returns true on success @@ -179,6 +194,11 @@ class HopScotchHashTable } virtual BucketType* insertKey(const Key& k){ + if (k == 0){ + cerr << "HopScotchHashTable::insertKey(): key 0 is not allowed." << endl; + return NULL; + } + int firstBucket = index(k); int cur = firstBucket; int end = modSize(firstBucket + H); @@ -208,15 +228,33 @@ class HopScotchHashTable } virtual BucketType* lookupKey(const Key& k){ + if (k == 0){ + cerr << "HopScotchHashTable::lookupKey(): key 0 is not allowed." << endl; + return NULL; + } + int firstBucket = index(k); - for (int i = 0; i < H; i++){ +#if _DEBUG + // keep track of how many hops till found + _numHops = 0; +#endif + // keep probing to the right + for (int i = 0; ; i = circularNext(i) ){ if (table[firstBucket + i].key == k) return &table[firstBucket + i]; +#if _DEBUG + else + _numHops++; +#endif } return NULL; } virtual void removeKey(const Key& k){ + if (k == 0){ + cerr << "HopScotchHashTable::remove(): key 0 is not allowed." << endl; + return; + } BucketType* pBucket = lookupKey(k); if (pBucket){ pBucket->key = 0; @@ -227,11 +265,6 @@ class HopScotchHashTable public: - virtual ~HopScotchHashTable(){} - HopScotchHashTable(unsigned int logSize = INIT_LOGSIZE, unsigned int H = INIT_H) :H(H),IntLinearProbingHashTable(logSize){ - assert(_size >= H); - } - }; ////////// test IntLinearProbingHashTable @@ -346,9 +379,6 @@ class HopScotchHashTableTest : public yasi::Test } } - void pushToRightOverZeroKey(){ - - } void circularDiff(){ IntHashTable8 h(3,4); ASSERT_EQ(8, h.size()); @@ -360,6 +390,33 @@ class HopScotchHashTableTest : public yasi::Test ASSERT_EQ(7, h.circularDiff(4, 3)); } + void insertRemoveLookup(){ + IntHashTable h(4, 4); // size 16, H=4 + ASSERT_EQ(16, h.size()); + ASSERT_EQ(0, h.population()); + ASSERT_EQ(6, h.H); + + // try to find an empty key + ASSERT_EQ(NULL, (int)h.lookupKey(7)); + ASSERT_EQ(NULL, (int)h.lookupKey(0)); + + // insert one key, find it, and remove it + h.put(5, 50); + ASSERT_EQ(true, h.contains(5)); + ASSERT_EQ(5, *h.lookupKey(5)); + ASSERT_EQ(50, *h.get(5)); + ASSERT_EQ(1, h.population()); + ASSERT_EQ(16, h.population()); + h.remove(5); + ASSERT_EQ(false, h.contains(5)); + ASSERT_EQ(NULL, (int)h.lookupKey(5)); + ASSERT_EQ(NULL, (int)h.get(5)); + ASSERT_EQ(0, h.population()); + ASSERT_EQ(16, h.population()); + + // insert many keys that + } + }; ADD_TEST_F(HopScotchHashTableTest, circularDiff); ADD_TEST_F(HopScotchHashTableTest, pushToRight);