抽象类dictionary.h:
#pragma once
#include <iostream>
#include <utility>
template<class K, class E>
class dictionary {
public:
virtual ~dictionary() {}
virtual bool empty() const = 0;
virtual int size() const = 0;
virtual std::pair<const K, E> *find(const K &) const = 0;
virtual void erase(const K &) = 0;
virtual void insert(const std::pair<const K, E> &) = 0;
};
hash函数hash.h:
#pragma once
#include <string>
#include <iostream>
template<class T>
class Hash;
template<>
class Hash<std::string> {
public:
size_t operator()(const std::string theKey) const {
unsigned long hashValue = 0;
int length = (int) theKey.length();
for (int i = 0; i < length; i++)
hashValue = 5 * hashValue + theKey.at(i);
return size_t(hashValue);
}
};
template<>
class Hash<int> {
public:
size_t operator()(const int key) const {
return size_t(key);
}
};
template<>
class Hash<short> {
public:
size_t operator()(const short key) const {
return size_t(key);
}
};
template<>
class Hash<long> {
public:
size_t operator()(const long key) const {
return size_t(key);
}
};
template<>
class Hash<long long> {
public:
size_t operator()(const long long key) const {
return size_t(key);
}
};
链表实现散列表hashChain.h:
#pragma once
#include "dictionary.h"
#include "hash.h"
#include "SortedChain.h"
template<class K, class E>
class hashChain : public dictionary<K, E> {
public:
hashChain(int theDivisor = 11);
~hashChain() {
delete[]table;
}
bool empty() const { return dSize == 0; }
int size() const { return dSize; }
std::pair<const K, E> *find(const K &) const;
void insert(const std::pair<const K, E> &);
void erase(const K &);
protected:
SortedChain<K, E> *table;
Hash<K> hash;
int divisor;
int dSize;
};
template<class K, class E>
hashChain<K, E>::hashChain(int theDivisor) {
divisor = theDivisor;
dSize = 0;
table = new SortedChain<K, E>[divisor];
}
template<class K, class E>
std::pair<const K, E> *hashChain<K, E>::find(const K &theKey) const {
return table[hash(theKey) % divisor].find(theKey);
}
template<class K, class E>
void hashChain<K, E>::insert(const std::pair<const K, E> &thePair) {
int homeBucket = (int) hash(thePair.first) % divisor;
int homeSize = table[homeBucket].size();
table[homeBucket].insert(thePair);
if (table[homeBucket].size() > homeSize)
dSize++;
}
template<class K, class E>
void hashChain<K, E>::erase(const K &theKey) {
table[hash(theKey) % divisor].erase(theKey);
}
template<class K, class E>
std::ostream &operator<<(std::ostream &out, const hashChain<K, E> &x) {
x.output(out);
return out;
}
开放式寻址hashTable.h:
#pragma once
#include "hash.h"
template<class K, class E>
class hashTable {
public:
hashTable(int theDivisor = 11);
~hashTable() { delete[]table; }
bool empty() const { return dSize == 0; }
int size() const { return dSize; }
std::pair<const K, E> *find(const K &) const;
void insert(const std::pair<const K, E> &);
void output(std::ostream &out) const;
int get_position(const K &theKey);
void erase(const K &theKey);
protected:
Hash<K> hash;
std::pair<const K, E> **table;
int divisor;
int dSize;
int search(const K &) const;
};
template<class K, class E>
int hashTable<K, E>::get_position(const K &theKey) {
for (int i = 0; i < divisor; ++i) {
if (table[i] != nullptr && table[i]->first == theKey)
return i;
}
return -1;
}
template<class K, class E>
void hashTable<K, E>::erase(const K &theKey) {
int b = hash(theKey) % divisor, cnt = 0;
if (table[b] == nullptr)
throw "error";
bool ok = false;
//ok 是否存在
if (table[b]->first == theKey) {
ok = true;
} else {
for (int i = (b + 1) % divisor; i != b; i = (i + 1) % divisor) {
if (table[i]->first == theKey) {
b = i;
ok = true;
break;
}
}
}
if (!ok)
throw "error";
delete table[b];
table[b] = nullptr;
dSize--;
for (int i = b + 1; i < divisor; ++i) {
if (table[i] == nullptr)
return;
if (hash(table[i]->first) % divisor <= b || hash(table[i]->first) % divisor > i) {
table[b] = new std::pair<const K, E>(std::make_pair(table[i]->first, table[i]->first));
delete table[i];
table[i] = nullptr;
cnt++;
b = i;
}
}
bool flag = false;
for (int i = 0; i < divisor; ++i) {
if (table[i] == nullptr)
return;
if (hash(table[i]->first) % divisor > i && hash(table[i]->first) % divisor <= b) {
table[b] = new std::pair<const K, E>(std::make_pair(table[i]->first, table[i]->first));
delete table[i];
table[i] = nullptr;
b = i;
++cnt;
flag = true;
break;
}
}
if (!flag)return;
for (int i = b + 1; i < divisor; ++i) {
if (table[i] == nullptr)return;
if (hash(table[i]->first) % divisor <= b || hash(table[i]->first) % divisor > i) {
table[b] = new std::pair<const K, E>(std::make_pair(table[i]->first, table[i]->first));
delete table[i];
table[i] = nullptr;
b = i;
++cnt;
}
}
}
template<class K, class E>
hashTable<K, E>::hashTable(int theDivisor) {
divisor = theDivisor;
dSize = 0;
table = new std::pair<const K, E> *[divisor];
for (int i = 0; i < divisor; ++i) {
table[i] = nullptr;
}
}
template<class K, class E>
int hashTable<K, E>::search(const K &theKey) const {
int i = (int) hash(theKey) % divisor;
int j = i;
do {
if (table[j] == nullptr || table[j]->first == theKey)return j;
j = (j + 1) % divisor;
} while (j != i);
return j;
}
template<class K, class E>
std::pair<const K, E> *hashTable<K, E>::find(const K &theKey) const {
int b = search(theKey);
if (table[b] == nullptr || table[b]->first != theKey)
return nullptr;
return table[b];
}
template<class K, class E>
void hashTable<K, E>::insert(const std::pair<const K, E> &thePair) {
int b = search(thePair.first);
if (table[b] == nullptr) {
table[b] = new std::pair<const K, E>(thePair);
dSize++;
} else {
if (table[b]->first == thePair.first)
table[b]->second = thePair.second;
else throw "full";
}
}
template<class K, class E>
void hashTable<K, E>::output(std::ostream &out) const {
for (int i = 0; i < divisor; i++) {
if (table[i] == nullptr) {
std::cout << "nullptr" << std::endl;
} else {
std::cout << table[i]->first << " " << table[i]->second << std::endl;
}
}
}
template<class K, class E>
std::ostream &operator<<(std::ostream &out, const hashTable<K, E> &x) {
x.output(out);
return out;
}