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"