hash table(全域散列法实现的哈希表)
利用每次重建哈希表时随机生成散列函数
#ifndef C11LEARN_HASHUNIVERSAL_H
#define C11LEARN_HASHUNIVERSAL_H
#include "Chain.h"
#include "../tools/random.h"
template<typename T>
class HashUniversal
{
protected:Chain<T>** array;int capacity;long long large_prime_numbers;long long a;long long b;
public:HashUniversal(int capacity = 1<<10,long long large_prime_numbers = 100001651);HashUniversal(const HashUniversal<T>& hashUniversal);const HashUniversal<T>& operator=(const HashUniversal<T>& hashUniversal);~HashUniversal();T & operator[](int key);bool remove(int key);protected:virtual int hashing(int key);void insert(Chain<T>* node);Chain<T>*search(int key);void clear();void copy(const HashUniversal<T> & hashUniversal);bool remove(Chain<T>* node);
};
template<typename T>
HashUniversal<T>::HashUniversal(int capacity,long long large_prime_numbers):capacity(capacity),large_prime_numbers(large_prime_numbers){array = new Chain<T>*[this->capacity];a = random_include_left_right(1ll,this->large_prime_numbers-1);b = random_include_left_right(0ll,this->large_prime_numbers-1);
}
template<typename T>
HashUniversal<T>::HashUniversal(const HashUniversal<T>& hashUniversal)
{capacity = hashUniversal.capacity;a = hashUniversal.a;b = hashUniversal.b;array = new Chain<T>*[this->capacity];large_prime_numbers = hashUniversal.large_prime_numbers;copy(hashUniversal);
}
template<typename T>
const HashUniversal<T>& HashUniversal<T>::operator=(const HashUniversal<T>& hashUniversal){if(this == &hashUniversal) return *this;clear();delete[] array;capacity = hashUniversal.capacity;a = hashUniversal.a;b = hashUniversal.b;array = new Chain<T>*[this->capacity];large_prime_numbers = hashUniversal.large_prime_numbers;copy(hashUniversal);return *this;
}
template<typename T>
HashUniversal<T>::~HashUniversal(){clear();if(array!= nullptr){delete [] array;array = nullptr;}
}
template<typename T>
T & HashUniversal<T>::operator[](int key){Chain<T>* node = search(key);if(node == nullptr){node = new Chain<T>();node->key = key;insert(node);}return node->value;
}
template<typename T>
int HashUniversal<T>::hashing(int key)
{return ((a*key+b)%large_prime_numbers)%capacity;
}
template<typename T>
void HashUniversal<T>::insert(Chain<T>* node){int pos = hashing(node->key);Chain<T>* current = array[pos];if(current == nullptr){array[pos] = node;}else{current->prev = node;node->next = current;}
}
template<typename T>
Chain<T>* HashUniversal<T>::search(int key){int pos = hashing(key);Chain<T>* current = array[pos];while (current!= nullptr && current->key != key)current = current->next;return current;
}
template<typename T>
void HashUniversal<T>::clear(){Chain<T>* current;Chain<T>* next;for (int i = 0; i < capacity; ++i) {current = array[i];while (current!= nullptr){next = current->next;delete current;current = next;}}
}
template<typename T>
void HashUniversal<T>::copy(const HashUniversal<T> & hashUniversal){Chain<T>* current;Chain<T>* prev;for (int i = 0; i < capacity; ++i) {prev = nullptr;current = hashUniversal.array[i];while (current!= nullptr){prev = current;current = current->next;}while (prev!= nullptr){Chain<T>* node = new Chain<T>();node->key = prev->key;node->value = prev->value;insert(node);prev = prev->prev;}}
}
template<typename T>
bool HashUniversal<T>::remove(int key){Chain<T>* node = search(key);if(node == nullptr){return false;}return remove(node);
}
template<typename T>
bool HashUniversal<T>::remove(Chain<T>* node){if(node == nullptr) return false;if(node->prev == nullptr){int pos = hashing(node->key);array[pos] = node->next;if(node->next!= nullptr){node->prev = nullptr;}}else{node->prev->next = node->next;if(node->next!= nullptr){node->next->prev = node->prev;}}delete node;node = nullptr;return true;
}
#endif //C11LEARN_HASHUNIVERSAL_H
辅助类
1⃣️Chain链接地址
2⃣️random_include_left_right链接地址
测试代码
HashUniversal<string> hashUniversal;hashUniversal[2] = "hello";hashUniversal[123456] = "world";cout << hashUniversal[2] << endl;cout << hashUniversal[123456] << endl;HashUniversal<string> hashUniversal1 = hashUniversal;cout << hashUniversal1[2] << endl;cout << hashUniversal1[123456] << endl;HashUniversal<string> hashUniversal2;hashUniversal2 = hashUniversal;cout << hashUniversal2[2] << endl;cout << hashUniversal2[123456] << endl;cout<<hashUniversal2.remove(123456)<<endl;