Skip to content

Commit

Permalink
Merge pull request #46 from Shu-AFK/main
Browse files Browse the repository at this point in the history
Fixed hashtable
  • Loading branch information
spirosmaggioros committed Apr 2, 2024
2 parents 71a6a4b + 490ff8f commit d52917f
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 118 deletions.
81 changes: 45 additions & 36 deletions src/classes/hash_table/hash_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
*/
template <typename KeyType, typename ValueType> class hash_table {
public:
using BucketType = std::unordered_map<size_t, std::list<std::pair<KeyType, ValueType>>>;

/**
* @brief Construct a new hash table object
*
Expand Down Expand Up @@ -121,31 +123,36 @@ template <typename KeyType, typename ValueType> class hash_table {

class Iterator;

Iterator begin() { return Iterator(bucketList, 0); }
Iterator begin() {
auto startIterator = bucketList.begin();
while (startIterator != bucketList.end() && startIterator->second.empty())
startIterator++;
return Iterator(startIterator, bucketList.end());
}

Iterator end() { return Iterator(bucketList, bucketList.size()); }
Iterator end() {
return Iterator(bucketList.end(), bucketList.end());
}

/**
* @brief << operator for hash_table class
* @return std::ostream&
*/
friend std::ostream &operator<<(std::ostream &out,
hash_table<KeyType, ValueType> &h) {
out << '[';
for (auto &[key, list] : h.bucketList) {
for (auto &pair : h.bucketList[key]) {
out << "{" << pair.first << ", " << pair.second << "} ";
friend std::ostream &operator<<(std::ostream &out, hash_table<KeyType, ValueType> &h) {
out << '[';
for (auto &[key, list] : h.bucketList) {
for (auto &pair : h.bucketList[key]) {
out << "{" << pair.first << ", " << pair.second << "} ";
}
out << '\n';
}
out << '\n';
}
out << ']';
out << ']';
return out;
}

private:
std::hash<KeyType> hash;
// std::vector<std::list<std::pair<KeyType, ValueType>>> bucketList;
std::unordered_map<size_t, std::list<std::pair<KeyType, ValueType>>>
bucketList;
std::hash<KeyType> hash;
BucketType bucketList;
};

/**
Expand All @@ -154,6 +161,11 @@ template <typename KeyType, typename ValueType> class hash_table {
template <typename KeyType, typename ValueType>
class hash_table<KeyType, ValueType>::Iterator {
private:
using BucketIterator = typename BucketType::iterator;
using ListIterator = typename std::list<std::pair<KeyType, ValueType>>::iterator;
BucketIterator bucketIter, bucketEnd;
ListIterator listIter;

std::unordered_map<size_t, std::list<std::pair<KeyType, ValueType>>>
bucketList;
std::vector<size_t> key_values;
Expand All @@ -165,14 +177,11 @@ class hash_table<KeyType, ValueType>::Iterator {
*
* @param bucket the bucket list
*/
explicit Iterator(
const std::unordered_map<size_t, std::list<std::pair<KeyType, ValueType>>>
&bucket,
int64_t __index) noexcept
: bucketList(bucket), index(__index) {
for (auto &x : bucketList) {
key_values.push_back(x.first);
}
explicit Iterator(BucketIterator start, BucketIterator end)
: bucketIter(start), bucketEnd(end) {
if (bucketIter != bucketEnd) {
listIter = bucketIter->second.begin();
}
}

/**
Expand All @@ -193,11 +202,14 @@ class hash_table<KeyType, ValueType>::Iterator {
*
* @return Iterator&
*/
Iterator &operator++() {
if (this->index < key_values.size()) {
this->index++;
}
return *(this);
Iterator& operator++() {
if (++listIter == bucketIter->second.end()) {
while (++bucketIter != bucketEnd && bucketIter->second.empty());
if (bucketIter != bucketEnd) {
listIter = bucketIter->second.begin();
}
}
return *this;
}

/**
Expand Down Expand Up @@ -242,12 +254,9 @@ class hash_table<KeyType, ValueType>::Iterator {
* the it.list that exist in the it.index
* @return false otherwise
*/
bool operator!=(const Iterator &it) {
std::list<std::pair<KeyType, ValueType>> l1 = bucketList[key_values[this->index]];
std::list<std::pair<KeyType, ValueType>> l2 =
bucketList[it.key_values[it.index]];
return this->index != it.index && l1 != l2;
return false;
bool operator!=(const Iterator& it) const {
return this->bucketIter != it.bucketIter
|| (bucketIter != bucketEnd && this->listIter != it.listIter);
}

/**
Expand All @@ -256,8 +265,8 @@ class hash_table<KeyType, ValueType>::Iterator {
* @return std::list<std::pair<KeyType, ValueType>> the list of the current
* index
*/
std::list<std::pair<KeyType, ValueType>> operator*() {
return bucketList[key_values[this->index]];
std::pair<KeyType, ValueType>& operator*() {
return *listIter;
}
};

Expand Down
173 changes: 94 additions & 79 deletions tests/hash_table/hash_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,102 +3,117 @@
#include <list>
#include <string>

TEST_CASE(
"checking insertions, overriding insertions and retrievals in hash table") {
hash_table<std::string, int> table;
TEST_CASE("checking insertions, overriding insertions and retrievals in hash table") {
hash_table<std::string, int> table;

table.insert("abc", 1);
table.insert("abc", 2);
table.insert("def", 3);
table.insert("abc", 1);
table.insert("abc", 2);
table.insert("def", 3);

REQUIRE(table.retrieve("abc") == 2);
REQUIRE(table.retrieve("ghi") == std::nullopt);
REQUIRE(table.retrieve("abc") == 2);
REQUIRE(table.retrieve("ghi") == std::nullopt);
}

TEST_CASE("checking removals in hash table") {
hash_table<std::string, int> table;
hash_table<std::string, int> table;

table.insert("abc", 1);
table.insert("def", 2);
table.remove("abc");
table.insert("abc", 1);
table.insert("def", 2);
table.remove("abc");

REQUIRE(table.retrieve("abc") == std::nullopt);
REQUIRE(table.retrieve("def") == 2);
REQUIRE(table.retrieve("abc") == std::nullopt);
REQUIRE(table.retrieve("def") == 2);
}

TEST_CASE("testing copy constructor in hash table") {
hash_table<int, std::string> table;
table.insert(1, "abc");
table.insert(2, "bcd");
table.insert(3, "cba");
hash_table<int, std::string> table;
table.insert(1, "abc");
table.insert(2, "bcd");
table.insert(3, "cba");

hash_table<int, std::string> table2(table);
hash_table<int, std::string> table2(table);

for (int i = 1; i <= 3; i++) {
REQUIRE(table.retrieve(i) == table2.retrieve(i));
}
for (int i = 1; i <= 3; i++) {
REQUIRE(table.retrieve(i) == table2.retrieve(i));
}
}

TEST_CASE("testing operator = in hash table") {
hash_table<int, std::string> table;
table.insert(1, "abc");
table.insert(2, "bcd");
table.insert(3, "cba");
hash_table<int, std::string> table;
table.insert(1, "abc");
table.insert(2, "bcd");
table.insert(3, "cba");

hash_table<int, std::string> table2 = table;
hash_table<int, std::string> table2 = table;

for (int i = 1; i <= 3; i++) {
REQUIRE(table.retrieve(i) == table2.retrieve(i));
}
for (int i = 1; i <= 3; i++) {
REQUIRE(table.retrieve(i) == table2.retrieve(i));
}
}

TEST_CASE("testing iterators in hash table") {
hash_table<int, std::string> table;
table.insert(1, "abc");
table.insert(2, "bcd");
table.insert(3, "cba");

std::vector<std::list<std::pair<int, std::string>>> v = {
{{1, "abc"}}, {{2, "bcd"}}, {{3, "cba"}}};

// auto iter = v.begin();
// for (auto it = table.begin(); it != table.end(); it++) {
// std::list<std::pair<int, std::string>> temp = *(it);
// REQUIRE(*(it) == *(iter));
// iter++;
// }
std::cout << '\n' << '\n';
hash_table<int, std::string> t2;
t2.insert(1, "a");
t2.insert(2, "b");
t2.insert(3, "c");
t2.insert(4, "d");

std::vector<std::list<std::pair<int, std::string>>> v2 = {
{{1, "a"}}, {{2, "b"}}, {{3, "c"}}, {{4, "d"}}};

// auto iter2 = v2.begin();
// for (auto it = t2.begin(); it != t2.end(); it++) {
// std::list<std::pair<int, std::string>> temp = *(it);
// REQUIRE(*(it) == *(iter2));
// iter2++;
// }

hash_table<int, std::string> t3;
t3.insert(1, "a");
t3.insert(2, "b");
t3.insert(3, "c");
t3.insert(4, "d");

std::vector<std::list<std::pair<int, std::string>>> v3;
auto it = t3.begin();
v3.push_back(*(it));
it++;
v3.push_back(*(it));
it--;
v3.push_back(*(it));

// std::vector<std::list<std::pair<int, std::string>>> check_v3 = {
// {{1, "a"}}, {{2, "b"}}, {{1, "a"}}};
// REQUIRE(v3 == check_v3);
TEST_CASE("checking hash_table<int, std::string> table") {
hash_table<int, std::string> table;
table.insert(1, "abc");
table.insert(2, "bcd");
table.insert(3, "cba");

std::vector<std::pair<int, std::string>> tablePairs;
for (auto it = table.begin(); it != table.end(); it++) {
tablePairs.push_back(*it);
}
std::sort(tablePairs.begin(), tablePairs.end());

std::vector<std::pair<int, std::string>> check_table = {
{1, "abc"},
{2, "bcd"},
{3, "cba"}};
std::sort(check_table.begin(), check_table.end());

REQUIRE(tablePairs == check_table);
}

TEST_CASE("checking hash_table<int, std::string> t2") {
hash_table<int, std::string> t2;
t2.insert(1, "a");
t2.insert(2, "b");
t2.insert(3, "c");
t2.insert(4, "d");

std::vector<std::pair<int, std::string>> t2Pairs;
for (auto it = t2.begin(); it != t2.end(); it++) {
t2Pairs.push_back(*it);
}
std::sort(t2Pairs.begin(), t2Pairs.end());

std::vector<std::pair<int, std::string>> check_t2 = {
{1, "a"},
{2, "b"},
{3, "c"},
{4, "d"}};
std::sort(check_t2.begin(), check_t2.end());

REQUIRE(t2Pairs == check_t2);
}

TEST_CASE("checking hash_table<int, std::string> t3") {
hash_table<int, std::string> t3;
t3.insert(1, "a");
t3.insert(2, "b");
t3.insert(3, "c");
t3.insert(4, "d");

std::vector<std::pair<int, std::string>> check_vec = {
{1, "a"},
{2, "b"},
{3, "c"},
{4, "d"}};
std::sort(check_vec.begin(), check_vec.end());

std::vector<std::pair<int, std::string>> vec;
for (auto it = t3.begin(); it != t3.end(); it++) {
vec.push_back(*it);
}
std::sort(vec.begin(), vec.end());

REQUIRE(vec == check_vec);
}
7 changes: 4 additions & 3 deletions tutorial/hash_table.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ ht.insert("apple", 1);
ht.insert("banana", 2);
ht.insert("carrot", 3);
for(auto it = ht.begin(); it != ht.end(); it++){
// *(it) returns the list of pairs that exist in each index
std::list<std::pair<std::string, int>> l = *(it);
for(auto it = ht.begin(); it != ht.end(); ++it) {
// *it returns the key-value pair at the iterator's current position
std::pair<std::string, int> p = *it;
std::cout << p.first << ": " << p.second << "\n";
}
```

0 comments on commit d52917f

Please sign in to comment.