#include <bits/stdc++.h>
using namespace std;
const static int limit = 2147483647 ;
// Problem 1 : Handling all letters and digits
int hash_string(string name, int limit) {
long long sum = 0;
const int base = 62;
for (auto ch : name) {
int val = 0;
if (islower(ch)) val = ch - 'a';
else if (isupper(ch)) val = 26 + (ch - 'A');
else if (isdigit(ch)) val = 52 + (ch - '0');
else continue;
sum = (sum * base + val) % limit;
}
return sum;
}
//Problem 4 : Folding for hashing
int Folding_Hash(string input){
long long hashValue = 0;
for(int i = 0 ; i < (int)input.size(); i+=4){
string word = input.substr(i, 4);
int blockHash = hash_string(word,limit);
hashValue =(hashValue + blockHash) % limit;
}
return hashValue;
}
// Problem 2 : Key based on multiple variables
class someObject {
public:
string str1, str2;
int number;
int hash(string str1, string str2, int number) {
return (hash_string(str1, limit) +
hash_string(str2, limit) +
hash_string(to_string(number), limit)) % limit;
}
};
// Problem 3 : Rehashing
class Entry {
public:
const static int Internal_limit = 65407;
string name; // key
string phoneNumber; // data
Entry(string name, string phoneNumber) : name(name), phoneNumber(phoneNumber) {}
int hash() const {
return hash_string(name, Internal_limit);
}
void print() const {
cout << setw(4) << " (" << name << ", " << phoneNumber << ") " << '\n';
}
};
class HashTable {
private:
int table_size{0};
int added{0};
double limitf;
vector<vector<Entry>> table;
public:
HashTable(int table_size, double limitf) : table_size(table_size), limitf(limitf) {
table.resize(table_size);
}
void put(const Entry &phone) {
if (Need_rehashing()) {
rehashing();
}
int idx = phone.hash() % table_size;
for (int i = 0; i < (int)table[idx].size(); i++) {
if (table[idx][i].name == phone.name) {
table[idx][i] = phone;
return;
}
}
added++;
table[idx].push_back(phone);
}
void put(const string &name, const string &phoneNumber) {
put(Entry(name, phoneNumber));
}
bool remove(const Entry &phone) {
int idx = phone.hash() % table_size;
for (int i = 0; i < (int)table[idx].size(); i++) {
if (table[idx][i].name == phone.name) {
swap(table[idx][i], table[idx].back());
table[idx].pop_back();
added--;
return true;
}
}
return false;
}
bool get(Entry &phone) const {
int idx = phone.hash() % table_size;
for (int i = 0; i < (int)table[idx].size(); i++) {
if (table[idx][i].name == phone.name) {
phone = table[idx][i];
return true;
}
}
return false;
}
void print_all() const {
for (int hash = 0; hash < table_size; hash++) {
if (table[hash].empty())
continue;
cout << "Hash " << hash << ": " << '\n';
for (const auto &entry : table[hash]) {
entry.print();
}
cout << '\n';
}
}
bool Need_rehashing() const {
return (double)added / table_size > limitf;
}
void rehashing() {
int old_table_size = table_size;
table_size *= 2;
vector<vector<Entry>> New_table(table_size);
added = 0;
for (int i = 0; i < old_table_size; i++) {
for (const auto &entry : table[i]) {
int new_idx = entry.hash() % table_size;
New_table[new_idx].push_back(entry);
added++;
}
}
table.swap(New_table);
}
};
class Node {
public:
Entry data;
Node* next;
Node* prev;
Node(Entry data) : data(data), next(nullptr), prev(nullptr) {}
};
class DLL {
private:
Node* head = nullptr;
Node* tail = nullptr;
int size = 0;
public:
void insert(const Entry &entry) {
Node* newNode = new Node(entry);
if (!head) {
head = tail = newNode;
}
else {
tail->next = newNode;
newNode->prev = tail;
tail = newNode;
}
size++;
}
void print_forward() const {
Node* temp = head;
while (temp) {
temp->data.print();
temp = temp->next;
}
cout << endl;
}
int get_size() const {
return size;
}
~DLL() {
Node* current = head;
while (current) {
Node* nextNode = current->next;
delete current;
current = nextNode;
}
}
};
// Problem 5 : Chaining using Double Linked List
class HashTable2 {
private:
int table_size{0}, added{0};
vector<DLL*> table;
public:
HashTable2(int size) : table_size(size), added(0) {
table.resize(size);
for (int i = 0; i < size; i++) {
table[i] = new DLL();
}
}
void put(const Entry &phone) {
int idx = phone.hash() % table_size;
table[idx]->insert(phone);
added++;
}
void put(const string &name, const string &phoneNumber) {
put(Entry(name, phoneNumber));
}
void print_all() const {
for (int hash = 0; hash < table_size; hash++) {
if (table[hash]->get_size() == 0)
continue;
cout << "Hash " << hash << ": " << endl;
table[hash]->print_forward();
}
}
~HashTable2() {
for (auto &dll : table) {
delete dll;
}
}
};
int main() {
HashTable ht(4, 0.75);
ht.put("Alice", "1234567890");
ht.put("Bob", "2345678901");
Entry search("Alice", "");
if (ht.get(search)) {
cout << "Found Alice's number: " << search.phoneNumber << '\n';
}
else {
cout << "Alice not found.\n";
}
cout <<"--------------------------\n\n";
HashTable2 ht2(7);
ht2.put("Charlie", "3456789012");
ht2.put("Diana", "4567890123");
ht2.put("Alice", "1234567890");
ht2.put("Bob", "2345678901");
ht2.put("manarmanora","749347");
cout << "HashTable2 contents:\n";
ht2.print_all();
}