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;