diff --git a/YASI_12/YASI_12.vcxproj b/YASI_12/YASI_12.vcxproj
index 89b6a9c..c1e149a 100644
--- a/YASI_12/YASI_12.vcxproj
+++ b/YASI_12/YASI_12.vcxproj
@@ -85,6 +85,7 @@
+
false
diff --git a/YASI_12/YASI_12.vcxproj.filters b/YASI_12/YASI_12.vcxproj.filters
index 03aea84..812c1d4 100644
--- a/YASI_12/YASI_12.vcxproj.filters
+++ b/YASI_12/YASI_12.vcxproj.filters
@@ -122,5 +122,8 @@
Header Files\Dictionary
+
+ Header Files
+
\ No newline at end of file
diff --git a/YASI_12/ds.IntLinearProbingHashTable.h b/YASI_12/ds.IntLinearProbingHashTable.h
new file mode 100644
index 0000000..ca713cf
--- /dev/null
+++ b/YASI_12/ds.IntLinearProbingHashTable.h
@@ -0,0 +1,89 @@
+#pragma once
+#include "common.h"
+#include "ds.LinearProbingHashTable.h"
+using namespace std;
+
+namespace yasi{
+ namespace ds{
+
+ // a hash table with integer key
+ template<
+ class Value = size_t,
+ class HashFunction = IntHashFunction >
+ class IntLinearProbingHashTable
+ : public LinearProbingHashTable <
+ size_t, Value, HashFunction, KVPair > {
+
+ ///////////////// enable testing ///////////////
+ friend class IntLinearProbingHashTableTest;
+ template
+ friend class LinearProbingHashTableTestBase;
+
+ public:
+ typedef size_t Key;
+ typedef KVPair EntryType; // must have a public member `key'
+ typedef EntryType BucketType; // each bucket holds an EntryType object
+ typedef EntryType Pair; // which is actually a key-value pair
+ typedef EntryType* BucketEntryPtr; // ptr to an entry object
+ typedef Key KeyType;
+ typedef Value ValueType;
+
+ protected:
+ typedef LinearProbingHashTable < size_t, Value, KVPairSimple, HashFunction >
+ base;
+
+
+ /////////// simplify some table accessor/modifier interface ///////////
+ virtual inline bool isNull(const int bucket) const{
+ return table[bucket].key == 0;
+ }
+ virtual inline void makeNull(const int bucket) const{
+ table[bucket].key = 0;
+ }
+ virtual inline bool isKeyZero(const Key* pKey) const{
+ return *pKey == 0;
+ }
+ virtual inline bool isKeyZero(const Key& key) const{
+ return key == 0;
+ }
+ virtual inline void setKeyZero(Key* pKey) const{
+ *pKey = 0;
+ }
+
+ public:
+
+ virtual ~IntLinearProbingHashTable(){}
+ IntLinearProbingHashTable(unsigned int logSize = INIT_LOGSIZE) :LinearProbingHashTable(logSize){}
+
+ };
+
+ ////////// test IntLinearProbingHashTable
+ // inherit tests from base class, just redefine the types
+
+ class IntLinearProbingHashTableTest : public LinearProbingHashTableTestBase<
+ IntLinearProbingHashTable >,
+ IntLinearProbingHashTable >,
+ IntLinearProbingHashTable >
+ >{
+ //
+ protected:
+ typedef IntLinearProbingHashTable > IntHashTable8;
+ typedef IntLinearProbingHashTable > IntHashTable16;
+ typedef IntHashTable16 IntHashTable; // default
+ typedef IntLinearProbingHashTable > IntHashTable32;
+ typedef IntHashTable::BucketType BucketType;
+ typedef IntHashTable::BucketEntryPtr BucketEntryPtr;
+ typedef IntHashTable::Pair Pair;
+ public:
+ // inherit all public tests
+
+ };
+ ADD_TEST_F(IntLinearProbingHashTableTest, insert);
+ ADD_TEST_F(IntLinearProbingHashTableTest, copyTable);
+ ADD_TEST_F(IntLinearProbingHashTableTest, growCondition);
+ ADD_TEST_F(IntLinearProbingHashTableTest, shrinkCondition);
+ ADD_TEST_F(IntLinearProbingHashTableTest, isKeyZero);
+ ADD_TEST_F(IntLinearProbingHashTableTest, remove);
+
+ }
+}
\ No newline at end of file
diff --git a/YASI_12/ds.LinearProbingHashTable.h b/YASI_12/ds.LinearProbingHashTable.h
index c8a8f0a..7952fc2 100644
--- a/YASI_12/ds.LinearProbingHashTable.h
+++ b/YASI_12/ds.LinearProbingHashTable.h
@@ -9,20 +9,70 @@ using namespace std;
namespace yasi{
namespace ds{
+ namespace testhash{
+ template
+ class IdentityFunction : public IHashFunction < Key > {
+ public:
+ virtual int operator()(const Key& n) const override{
+ return n;
+ }
+ };
+ template
+ class Mod8Function : public IHashFunction < Key > {
+ public:
+ static const unsigned int modulus = 8;
+ virtual int operator()(const Key& n) const override{
+ return n % 8;
+ }
+ };
+ template
+ class Mod16Function : public IHashFunction < Key > {
+ public:
+ static const unsigned int modulus = 16;
+ virtual int operator()(const Key& n) const override{
+ return n % 16;
+ }
+ };
+ template
+ class Mod32Function : public IHashFunction < Key > {
+ public:
+ static const unsigned int modulus = 32;
+ virtual int operator()(const Key& n) const override{
+ return n % 32;
+ }
+ };
+ // mod 16 by default
+ template
+ class ModFunction : public IHashFunction < Key > {
+ public:
+ unsigned int modulus;
+ ModFunction() : modulus(16){}
+ virtual int operator()(const Key& n) const override{
+ return n % modulus;
+ }
+ };
+
+ } // namespace testhash
+ using namespace testhash;
+
+
template<
class Key,
class Value = Key,
- class EntryType = KeyOnly, // must have a public member `key'
class HashFunction = IntHashFunction,
+ class EntryType = KVPair, // must have key and value fields
class Pred = KVPairEqualityPredicate
>
class LinearProbingHashTable : public HashTableBase <
Key,
Value,
- EntryType, // storing objects, not pointers
+ KVPair, // storing objects, not pointers
HashFunction > {
///////////////// enable testing ///////////////////
+ template
+ friend class LinearProbingHashTableTestBase;
friend class LinearProbingHashTableTest;
+
public:
// an EntryType object is stored in the table
@@ -40,7 +90,7 @@ namespace ds{
char* _pZeroKey; // all zeros up to #bytes of a Key; used to check if a Key is zero
char* _pZeroValue; // all zeros up to #bytes of a Value; used to set a Value to zero
-#if 1
+
inline unsigned int circularNext(const int index) const{
return modSize(index + 1);
}
@@ -62,7 +112,7 @@ namespace ds{
// the key must be present in the table
- BucketEntryPtr lookupKey(const Key& k) const {
+ virtual BucketEntryPtr lookupKey(const Key& k) const {
// test the zero key
if (isKeyZero(&k)){
if (_zeroUsed) return const_cast(&_zeroKeyEntry);
@@ -98,7 +148,7 @@ namespace ds{
}
}
- BucketEntryPtr insertKey(const Key& k) {
+ virtual BucketEntryPtr insertKey(const Key& k) {
// insert/update the entry with hashcode 0
if ( isKeyZero(&k)){
@@ -225,9 +275,9 @@ namespace ds{
table[bucket] = Pair(k);
// if we stored pointers, we would have done new Pair(k)
}
-#endif
- virtual bool isBucketEmpty(const int bucket) const override {
- return false; // return isNull(bucket);
+
+ virtual inline bool isBucketEmpty(const int bucket) const override {
+ return isNull(bucket);
}
virtual void copyTable(BucketType* oldTable, const unsigned int oldSize) override {
// the zeroPair stays intact because it is determined by key, not hash value
@@ -287,7 +337,6 @@ namespace ds{
return lookupKey(key) != NULL;
}
virtual void remove(const Key& k) override {
-#if 1
// zero key
if (isKeyZero(&k)){
if (_zeroUsed) {
@@ -375,76 +424,37 @@ namespace ds{
// cannot remove; done
}
return;
-#endif
+
}
};
- class LinearProbingHashTableTest : public yasi::Test{
- protected:
-
+ ///////////////////////// testing ////////////////////////
+ typedef LinearProbingHashTable > _LinProbHT8;
+ typedef LinearProbingHashTable > _LinProbHT16;
+ typedef LinearProbingHashTable > _LinProbHT32;
- template
- class IdentityFunction : public IHashFunction{
- public:
- virtual int operator()(const Key& n) const override{
- return n;
- }
- };
- template
- class Mod8Function : public IHashFunction{
- public:
- static const unsigned int modulus = 8;
- virtual int operator()(const Key& n) const override{
- return n % 8;
- }
- };
- template
- class Mod16Function : public IHashFunction{
- public:
- static const unsigned int modulus = 16;
- virtual int operator()(const Key& n) const override{
- return n % 16;
- }
- };
- template
- class Mod32Function : public IHashFunction{
- public:
- static const unsigned int modulus = 32;
- virtual int operator()(const Key& n) const override{
- return n % 32;
- }
- };
- // mod 16 by default
- template
- class ModFunction : public IHashFunction{
- public:
- unsigned int modulus;
- ModFunction() : modulus(16){}
- virtual int operator()(const Key& n) const override{
- return n % modulus;
- }
- };
-
- //bucketKey(h,x)
- // h.mytable[0]->key
- // h.mytable[bucket]->key
- // h.mytable[x]->key
-
- typedef LinearProbingHashTable, Mod8Function > IntHashTable8;
- typedef LinearProbingHashTable, Mod16Function > IntHashTable16;
+ template<
+ class IntHashTable8 = _LinProbHT8,
+ class IntHashTable16 = _LinProbHT16,
+ class IntHashTable32 = _LinProbHT32
+ >
+ class LinearProbingHashTableTestBase : public yasi::Test{
+ protected:
+ //typedef LinearProbingHashTable > IntHashTable8;
+ //typedef LinearProbingHashTable > IntHashTable16;
+ //typedef LinearProbingHashTable > IntHashTable32;
typedef IntHashTable16 IntHashTable; // default
- typedef LinearProbingHashTable, Mod32Function > IntHashTable32;
- typedef IntHashTable::BucketType BucketType;
- typedef IntHashTable::BucketEntryPtr BucketEntryPtr;
- typedef IntHashTable::Pair Pair;
+ typedef typename IntHashTable::BucketType BucketType;
+ typedef typename IntHashTable::BucketEntryPtr BucketEntryPtr;
+ typedef typename IntHashTable::Pair Pair;
public:
-#if 1
- void insert(){
+
+ virtual void insert(){
IntHashTable h(4);
ASSERT_EQ(16, h.size()) << "size not 16";
@@ -460,91 +470,91 @@ namespace ds{
cout << h;
ASSERT_EQ(3, h.population()) << "pop not 3";
}
- {
- string str = "insert 20, which should go to bucket 7";
- int key = 20;
- int bucket = 7;
- SCOPED_TRACE(str);
- BucketEntryPtr p = h.insertKey(key);
- p->value = key; // assign the value
- cout << str << endl << h;
- ASSERT_NE(true, h.isNull(bucket)) << "bucket " << bucket << " NULL";
- ASSERT_EQ(p, h.entryptr(bucket)) << key << " not in bucket " << bucket;
- ASSERT_EQ(key, h.key(bucket)) << key << " not in bucket " << bucket;
- }
- {
- string str = "insert 23, which should go to bucket 8";
- int key = 23;
- int bucket = 8;
- SCOPED_TRACE(str);
- BucketEntryPtr p = h.insertKey(key);
- p->value = key; // assign the value
- cout << str << endl << h;
- ASSERT_NE(true, h.isNull(bucket)) << "bucket " << bucket << " NULL";
- ASSERT_EQ(p, h.entryptr(bucket)) << key << " not in bucket " << bucket;
- ASSERT_EQ(key, h.key(bucket)) << key << " not in bucket " << bucket;
- }
- {
- string str = "insert 20, which is already in bucket 7";
- SCOPED_TRACE(str);
- int key = 20;
- int bucket = 7;
- SCOPED_TRACE(str);
- BucketEntryPtr p = h.insertKey(key);
- cout << str << endl << h;
- ASSERT_NE(true, h.isNull(bucket)) << "bucket " << bucket << " NULL";
- ASSERT_EQ(p, h.entryptr(bucket)) << key << " not in bucket " << bucket;
- ASSERT_EQ(key, h.key(bucket)) << key << " not in bucket " << bucket;
- ASSERT_EQ(key, h.value(bucket)) << key << " not in bucket " << bucket;
- }
- {
- h.insert(13, 13);
- h.insert(14, 14);
- h.insert(15, 15);
- //
- string str = "search round the table; now insert 16, should go to bucket 0";
- int key = 16;
- int bucket = 0;
- SCOPED_TRACE(str);
- BucketEntryPtr p = h.insertKey(key);
- p->value = key; // assign the value
- cout << str << endl << h;
- ASSERT_NE(true, h.isNull(bucket)) << "bucket " << bucket << " NULL";
- ASSERT_EQ(p, h.entryptr(bucket)) << key << " not in bucket " << bucket;
- ASSERT_EQ(key, h.key(bucket)) << key << " not in bucket " << bucket;
-
- }
- {
- string str = "search round the table; now insert 29, should go to bucket 1";
- int key = 29;
- int bucket = 1;
- SCOPED_TRACE(str);
- BucketEntryPtr p = h.insertKey(key);
- p->value = key; // assign the value
- cout << str << endl << h;
- ASSERT_NE(true, h.isNull(bucket)) << "bucket " << bucket << " NULL";
- ASSERT_EQ(p, h.entryptr(bucket)) << key << " not in bucket " << bucket;
- ASSERT_EQ(key, h.key(bucket)) << key << " not in bucket " << bucket;
-
- }
- {
- string str = "insert 0; should go to the zero element";
- int key = 0;
- SCOPED_TRACE(str);
- ASSERT_EQ(false, h._zeroUsed) << "_zeroUsed true";
- int prevPop = h.population();
- BucketEntryPtr p = h.insertKey(key);
- p->value = 100; // assign the value
- cout << str << endl << h;
- ASSERT_EQ(true, h._zeroUsed) << "_zeroUsed false";
- ASSERT_EQ(p, &h._zeroKeyEntry) << " zero key not in zeroPair";
- ASSERT_EQ(prevPop+1, h.population()) << "population did not increase";
- ASSERT_EQ(key, h._zeroKeyEntry.key) << key << " not in zeroPair";
- }
-
- }
-
- void copyTable(){
+ {
+ string str = "insert 20, which should go to bucket 7";
+ int key = 20;
+ int bucket = 7;
+ SCOPED_TRACE(str);
+ BucketEntryPtr p = h.insertKey(key);
+ p->value = key; // assign the value
+ cout << str << endl << h;
+ ASSERT_NE(true, h.isNull(bucket)) << "bucket " << bucket << " NULL";
+ ASSERT_EQ(p, h.entryptr(bucket)) << key << " not in bucket " << bucket;
+ ASSERT_EQ(key, h.key(bucket)) << key << " not in bucket " << bucket;
+ }
+ {
+ string str = "insert 23, which should go to bucket 8";
+ int key = 23;
+ int bucket = 8;
+ SCOPED_TRACE(str);
+ BucketEntryPtr p = h.insertKey(key);
+ p->value = key; // assign the value
+ cout << str << endl << h;
+ ASSERT_NE(true, h.isNull(bucket)) << "bucket " << bucket << " NULL";
+ ASSERT_EQ(p, h.entryptr(bucket)) << key << " not in bucket " << bucket;
+ ASSERT_EQ(key, h.key(bucket)) << key << " not in bucket " << bucket;
+ }
+ {
+ string str = "insert 20, which is already in bucket 7";
+ SCOPED_TRACE(str);
+ int key = 20;
+ int bucket = 7;
+ SCOPED_TRACE(str);
+ BucketEntryPtr p = h.insertKey(key);
+ cout << str << endl << h;
+ ASSERT_NE(true, h.isNull(bucket)) << "bucket " << bucket << " NULL";
+ ASSERT_EQ(p, h.entryptr(bucket)) << key << " not in bucket " << bucket;
+ ASSERT_EQ(key, h.key(bucket)) << key << " not in bucket " << bucket;
+ ASSERT_EQ(key, h.value(bucket)) << key << " not in bucket " << bucket;
+ }
+ {
+ h.insert(13, 13);
+ h.insert(14, 14);
+ h.insert(15, 15);
+ //
+ string str = "search round the table; now insert 16, should go to bucket 0";
+ int key = 16;
+ int bucket = 0;
+ SCOPED_TRACE(str);
+ BucketEntryPtr p = h.insertKey(key);
+ p->value = key; // assign the value
+ cout << str << endl << h;
+ ASSERT_NE(true, h.isNull(bucket)) << "bucket " << bucket << " NULL";
+ ASSERT_EQ(p, h.entryptr(bucket)) << key << " not in bucket " << bucket;
+ ASSERT_EQ(key, h.key(bucket)) << key << " not in bucket " << bucket;
+
+ }
+ {
+ string str = "search round the table; now insert 29, should go to bucket 1";
+ int key = 29;
+ int bucket = 1;
+ SCOPED_TRACE(str);
+ BucketEntryPtr p = h.insertKey(key);
+ p->value = key; // assign the value
+ cout << str << endl << h;
+ ASSERT_NE(true, h.isNull(bucket)) << "bucket " << bucket << " NULL";
+ ASSERT_EQ(p, h.entryptr(bucket)) << key << " not in bucket " << bucket;
+ ASSERT_EQ(key, h.key(bucket)) << key << " not in bucket " << bucket;
+
+ }
+ {
+ string str = "insert 0; should go to the zero element";
+ int key = 0;
+ SCOPED_TRACE(str);
+ ASSERT_EQ(false, h._zeroUsed) << "_zeroUsed true";
+ int prevPop = h.population();
+ BucketEntryPtr p = h.insertKey(key);
+ p->value = 100; // assign the value
+ cout << str << endl << h;
+ ASSERT_EQ(true, h._zeroUsed) << "_zeroUsed false";
+ ASSERT_EQ(p, &h._zeroKeyEntry) << " zero key not in zeroPair";
+ ASSERT_EQ(prevPop + 1, h.population()) << "population did not increase";
+ ASSERT_EQ(key, h._zeroKeyEntry.key) << key << " not in zeroPair";
+ }
+
+ }
+
+ virtual void copyTable(){
IntHashTable16 h1(4);
IntHashTable32 h2(5);
@@ -584,7 +594,7 @@ namespace ds{
DELETE_ARR_SAFE(pKeys);
}
- void remove(){
+ virtual void remove(){
IntHashTable h(4);
ASSERT_EQ(16, h.size()) << "size not 16";
@@ -608,74 +618,74 @@ namespace ds{
ASSERT_EQ(8, h.population()) << "population not 8";
}
- {
- SCOPED_TRACE("remove 4");
- h.remove(4);
- //// 46 - - - - 5 6 7 - - - - 12 - 14 30
- //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- cout << h;
- ASSERT_EQ(16, h.size()) << "size not 16";
- ASSERT_EQ(NULL, (int)h.lookupKey(4)) << "key " << 4 << " not NULL";
- ASSERT_EQ(5, h.key(5)) << "[5] not " << 5;
- ASSERT_EQ(6, h.key(6)) << "[6] not " << 6;
- ASSERT_EQ(7, h.key(7)) << "[7] not " << 7;
- ASSERT_EQ(7, h.population()) << "population not 7";
- }
- {
- SCOPED_TRACE("remove 6");
- cout << "before removing 6\n" << h;
- h.remove(6);
- //// 46 - - - - 5 - 7 - - - - 12 - 14 30
- //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- ASSERT_EQ(16, h.size()) << "size not 16";
- ASSERT_EQ(6, h.population()) << "population not 6";
- cout << "after removing 6\n" << h;
- ASSERT_EQ(NULL, (int)h.lookupKey(6)) << "key " << 6 << " not NULL";
- ASSERT_EQ(5, h.key(5)) << "key " << 5 << " misplaced";
- ASSERT_EQ(7, h.key(7)) << "key " << 7 << " misplaced";
- }
- {
- SCOPED_TRACE("remove simple 2-item bucket");
- h.insert(85, 85);
- //// 46 - - - - 5 85 7 - - - - 12 - 14 30
- //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- ASSERT_EQ(7, h.population()) << "population not 7";
- ASSERT_EQ(85, h.key(6)) << "[6] not 85";
- ASSERT_EQ(16, h.size()) << "size not 16";
- h.remove(5);
- //// 46 - - - - 85 - 7 - - - - 12 - 14 30
- //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- ASSERT_EQ(NULL, (int)h.lookupKey(5)) << "key " << 5 << " not NULL";
- ASSERT_EQ(85, h.key(5)) << "key " << 85 << " misplaced";
- ASSERT_EQ(true, h.isNull(6)) << "[6] not NULL";
- ASSERT_EQ(7, h.key(7)) << "key " << 7 << " misplaced";
-
- // put 5 back
- h.insert(5,5);
- //// 46 - - - - 85 5 7 - - - - 12 - 14 30
- //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- ASSERT_EQ(5, h.key(6)) << "key " << 5 << " misplaced";
-
- // delete 5
- h.remove(5);
- //// 46 - - - - 85 - 7 - - - - 12 - 14 30
- //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- ASSERT_EQ(16, h.size()) << "size not 16";
- ASSERT_EQ(NULL, (int)h.lookupKey(5)) << "key " << 5 << " not NULL";
- ASSERT_EQ(85, h.key(5)) << "key " << 85 << " misplaced";
- ASSERT_EQ(true, h.isNull(6)) << "[6) not NULL";
- ASSERT_EQ(7, h.key(7)) << "key " << 7 << " misplaced";
-
- // for consistency later on, replace 85 with 5
- h.remove(85);
- h.insert(5, 5);
- //// 46 - - - - 5 - 7 - - - - 12 - 14 30
- //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- ASSERT_EQ(16, h.size()) << "size not 16";
- ASSERT_EQ(5, h.key(5)) << "[5] not 5";
- ASSERT_EQ(true, h.isNull(6)) << "[6] not NULL";
- ASSERT_EQ(7, h.key(7)) << "key " << 7 << " misplaced";
- }
+ {
+ SCOPED_TRACE("remove 4");
+ h.remove(4);
+ //// 46 - - - - 5 6 7 - - - - 12 - 14 30
+ //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ cout << h;
+ ASSERT_EQ(16, h.size()) << "size not 16";
+ ASSERT_EQ(NULL, (int)h.lookupKey(4)) << "key " << 4 << " not NULL";
+ ASSERT_EQ(5, h.key(5)) << "[5] not " << 5;
+ ASSERT_EQ(6, h.key(6)) << "[6] not " << 6;
+ ASSERT_EQ(7, h.key(7)) << "[7] not " << 7;
+ ASSERT_EQ(7, h.population()) << "population not 7";
+ }
+ {
+ SCOPED_TRACE("remove 6");
+ cout << "before removing 6\n" << h;
+ h.remove(6);
+ //// 46 - - - - 5 - 7 - - - - 12 - 14 30
+ //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ ASSERT_EQ(16, h.size()) << "size not 16";
+ ASSERT_EQ(6, h.population()) << "population not 6";
+ cout << "after removing 6\n" << h;
+ ASSERT_EQ(NULL, (int)h.lookupKey(6)) << "key " << 6 << " not NULL";
+ ASSERT_EQ(5, h.key(5)) << "key " << 5 << " misplaced";
+ ASSERT_EQ(7, h.key(7)) << "key " << 7 << " misplaced";
+ }
+ {
+ SCOPED_TRACE("remove simple 2-item bucket");
+ h.insert(85, 85);
+ //// 46 - - - - 5 85 7 - - - - 12 - 14 30
+ //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ ASSERT_EQ(7, h.population()) << "population not 7";
+ ASSERT_EQ(85, h.key(6)) << "[6] not 85";
+ ASSERT_EQ(16, h.size()) << "size not 16";
+ h.remove(5);
+ //// 46 - - - - 85 - 7 - - - - 12 - 14 30
+ //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ ASSERT_EQ(NULL, (int)h.lookupKey(5)) << "key " << 5 << " not NULL";
+ ASSERT_EQ(85, h.key(5)) << "key " << 85 << " misplaced";
+ ASSERT_EQ(true, h.isNull(6)) << "[6] not NULL";
+ ASSERT_EQ(7, h.key(7)) << "key " << 7 << " misplaced";
+
+ // put 5 back
+ h.insert(5, 5);
+ //// 46 - - - - 85 5 7 - - - - 12 - 14 30
+ //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ ASSERT_EQ(5, h.key(6)) << "key " << 5 << " misplaced";
+
+ // delete 5
+ h.remove(5);
+ //// 46 - - - - 85 - 7 - - - - 12 - 14 30
+ //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ ASSERT_EQ(16, h.size()) << "size not 16";
+ ASSERT_EQ(NULL, (int)h.lookupKey(5)) << "key " << 5 << " not NULL";
+ ASSERT_EQ(85, h.key(5)) << "key " << 85 << " misplaced";
+ ASSERT_EQ(true, h.isNull(6)) << "[6) not NULL";
+ ASSERT_EQ(7, h.key(7)) << "key " << 7 << " misplaced";
+
+ // for consistency later on, replace 85 with 5
+ h.remove(85);
+ h.insert(5, 5);
+ //// 46 - - - - 5 - 7 - - - - 12 - 14 30
+ //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ ASSERT_EQ(16, h.size()) << "size not 16";
+ ASSERT_EQ(5, h.key(5)) << "[5] not 5";
+ ASSERT_EQ(true, h.isNull(6)) << "[6] not NULL";
+ ASSERT_EQ(7, h.key(7)) << "key " << 7 << " misplaced";
+ }
// add several entries that map into bucket 5
h.insert(21, 21);
@@ -716,45 +726,45 @@ namespace ds{
ASSERT_EQ(true, h.isNull(13)) << "[13] not NULL";
ASSERT_EQ(14, h.key(14)) << "[14] not 14";
}
- {
- SCOPED_TRACE("remove 21");
- //delete 21
- h.remove(21);
- //// 46 - - - - 37 53 7 23 39 - - 12 - 14 30
- //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- ASSERT_EQ(16, h.size()) << "size not 16";
- ASSERT_EQ(NULL, (int)h.lookupKey(21)) << "key " << 21 << " not NULL";
- ASSERT_EQ(37, h.key(5)) << "[5] not 37";
- ASSERT_EQ(53, h.key(6)) << "[6] not 53";
- ASSERT_EQ(7, h.key(7)) << "[7] not 7";
- ASSERT_EQ(23, h.key(8)) << "[8] not 23";
- ASSERT_EQ(39, h.key(9)) << "[9] not 39";
- ASSERT_EQ(true, h.isNull(10)) << "[10] not NULL";
- ASSERT_EQ(true, h.isNull(11)) << "[11] not NULL";
- ASSERT_EQ(12, h.key(12)) << "[12] not 12";
- ASSERT_EQ(true, h.isNull(13)) << "[13] not NULL";
- ASSERT_EQ(14, h.key(14)) << "[14] not 14";
- }
+ {
+ SCOPED_TRACE("remove 21");
+ //delete 21
+ h.remove(21);
+ //// 46 - - - - 37 53 7 23 39 - - 12 - 14 30
+ //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ ASSERT_EQ(16, h.size()) << "size not 16";
+ ASSERT_EQ(NULL, (int)h.lookupKey(21)) << "key " << 21 << " not NULL";
+ ASSERT_EQ(37, h.key(5)) << "[5] not 37";
+ ASSERT_EQ(53, h.key(6)) << "[6] not 53";
+ ASSERT_EQ(7, h.key(7)) << "[7] not 7";
+ ASSERT_EQ(23, h.key(8)) << "[8] not 23";
+ ASSERT_EQ(39, h.key(9)) << "[9] not 39";
+ ASSERT_EQ(true, h.isNull(10)) << "[10] not NULL";
+ ASSERT_EQ(true, h.isNull(11)) << "[11] not NULL";
+ ASSERT_EQ(12, h.key(12)) << "[12] not 12";
+ ASSERT_EQ(true, h.isNull(13)) << "[13] not NULL";
+ ASSERT_EQ(14, h.key(14)) << "[14] not 14";
+ }
- {
- SCOPED_TRACE("remove 23");
- //delete 23
- h.remove(23);
- //// 46 - - - - 37 53 7 39 - - - 12 - 14 30
- //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- ASSERT_EQ(16, h.size()) << "size not 16";
- ASSERT_EQ(NULL, (int)h.lookupKey(23)) << "key " << 23 << " not NULL";
- ASSERT_EQ(37, h.key(5)) << "[5] not 37";
- ASSERT_EQ(53, h.key(6)) << "[6] not 53";
- ASSERT_EQ(7, h.key(7)) << "[7] not 7";
- ASSERT_EQ(39, h.key(8)) << "[8] not 39";
- ASSERT_EQ(true, h.isNull(9)) << "[9] not NULL";
- ASSERT_EQ(true, h.isNull(10)) << "[10] not NULL";
- ASSERT_EQ(true, h.isNull(11)) << "[11] not NULL";
- ASSERT_EQ(12, h.key(12)) << "[12] not 12";
- ASSERT_EQ(true, h.isNull(13)) << "[13] not NULL";
- ASSERT_EQ(14, h.key(14)) << "[14] not 14";
- }
+ {
+ SCOPED_TRACE("remove 23");
+ //delete 23
+ h.remove(23);
+ //// 46 - - - - 37 53 7 39 - - - 12 - 14 30
+ //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ ASSERT_EQ(16, h.size()) << "size not 16";
+ ASSERT_EQ(NULL, (int)h.lookupKey(23)) << "key " << 23 << " not NULL";
+ ASSERT_EQ(37, h.key(5)) << "[5] not 37";
+ ASSERT_EQ(53, h.key(6)) << "[6] not 53";
+ ASSERT_EQ(7, h.key(7)) << "[7] not 7";
+ ASSERT_EQ(39, h.key(8)) << "[8] not 39";
+ ASSERT_EQ(true, h.isNull(9)) << "[9] not NULL";
+ ASSERT_EQ(true, h.isNull(10)) << "[10] not NULL";
+ ASSERT_EQ(true, h.isNull(11)) << "[11] not NULL";
+ ASSERT_EQ(12, h.key(12)) << "[12] not 12";
+ ASSERT_EQ(true, h.isNull(13)) << "[13] not NULL";
+ ASSERT_EQ(14, h.key(14)) << "[14] not 14";
+ }
h.insert(62, 62);
h.insert(17, 17);
//// 46 62 17 - - 37 53 39 - - - - 12 - 14 30
@@ -778,30 +788,30 @@ namespace ds{
ASSERT_EQ(30, h.key(15)) << "[15] not 30";
}
- {
- SCOPED_TRACE("remove 30");
- //delete 30
- h.remove(30);
- //// - 17 - - - 37 53 39 - - - - 12 - 14 62
- //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- ASSERT_EQ(16, h.size()) << "size not 16";
- ASSERT_EQ(NULL, (int)h.lookupKey(30)) << "key " << 30 << " not NULL";
- ASSERT_EQ(17, h.key(1)) << "[1] not 17";
- ASSERT_EQ(true, h.isNull(0)) << "[0] not NULL";
- ASSERT_EQ(14, h.key(14)) << "[14] not 14";
- ASSERT_EQ(62, h.key(15)) << "[15] not 62";
- }
- {
- SCOPED_TRACE("remove 14");
- //delete 14
- h.remove(14);
- //// - - - - - 37 53 39 - - - - 12 - 62 -
- //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- ASSERT_EQ(16, h.size()) << "size not 16";
- ASSERT_EQ(NULL, (int)h.lookupKey(14)) << "key " << 14 << " not NULL";
- ASSERT_EQ(62, h.key(14)) << "[14] not 62";
- ASSERT_EQ(true, h.isNull(15)) << "[15] not NULL";
- }
+ {
+ SCOPED_TRACE("remove 30");
+ //delete 30
+ h.remove(30);
+ //// - 17 - - - 37 53 39 - - - - 12 - 14 62
+ //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ ASSERT_EQ(16, h.size()) << "size not 16";
+ ASSERT_EQ(NULL, (int)h.lookupKey(30)) << "key " << 30 << " not NULL";
+ ASSERT_EQ(17, h.key(1)) << "[1] not 17";
+ ASSERT_EQ(true, h.isNull(0)) << "[0] not NULL";
+ ASSERT_EQ(14, h.key(14)) << "[14] not 14";
+ ASSERT_EQ(62, h.key(15)) << "[15] not 62";
+ }
+ {
+ SCOPED_TRACE("remove 14");
+ //delete 14
+ h.remove(14);
+ //// - - - - - 37 53 39 - - - - 12 - 62 -
+ //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ ASSERT_EQ(16, h.size()) << "size not 16";
+ ASSERT_EQ(NULL, (int)h.lookupKey(14)) << "key " << 14 << " not NULL";
+ ASSERT_EQ(62, h.key(14)) << "[14] not 62";
+ ASSERT_EQ(true, h.isNull(15)) << "[15] not NULL";
+ }
}
{
@@ -850,8 +860,8 @@ namespace ds{
}
}
-
- void growCondition(){
+
+ virtual void growCondition(){
IntHashTable16 h1(4);
int i = 0;
@@ -873,7 +883,7 @@ namespace ds{
ASSERT_EQ(popLimit + 1, h1.population()) << "h1 pop not " << popLimit + 1;
}
}
- void shrinkCondition(){
+ virtual void shrinkCondition(){
IntHashTable16 h1(4);
int i = 0;
@@ -902,8 +912,8 @@ namespace ds{
ASSERT_EQ(popLimit - 1, h1.population()) << "h1 pop not " << popLimit - 1;
}
}
-#endif
- void isKeyZero(){
+
+ virtual void isKeyZero(){
//struct MyStruct{
// int a;
// float b;
@@ -984,6 +994,11 @@ namespace ds{
}
};
+ class LinearProbingHashTableTest : public LinearProbingHashTableTestBase < _LinProbHT8, _LinProbHT16, _LinProbHT32> {
+ public:
+ // inherit all tests from base
+ };
+
ADD_TEST_F(LinearProbingHashTableTest, insert);
ADD_TEST_F(LinearProbingHashTableTest, copyTable);
ADD_TEST_F(LinearProbingHashTableTest, growCondition);
@@ -991,5 +1006,8 @@ namespace ds{
ADD_TEST_F(LinearProbingHashTableTest, isKeyZero);
ADD_TEST_F(LinearProbingHashTableTest, remove);
+
+
+
}
}
\ No newline at end of file
diff --git a/YASI_12/main.cpp b/YASI_12/main.cpp
index 1c2fa49..114dcbe 100644
--- a/YASI_12/main.cpp
+++ b/YASI_12/main.cpp
@@ -8,6 +8,7 @@
#include "ds.priorityqueue.h"
#include "ds.BSTDictionary.h"
#include "ds.separatechaininghashtable.h"
+#include "ds.intlinearprobinghashtable.h"
#include "ds.linearprobinghashtable.h"
//#include "Sorter.h"