hashtable的C++实现,使用两种常用的解决冲突的方式,使用时需要自己提供针对HashedObj的hash函数。
1、分离连接法(separate chaining)
#include <vector>
#include <list>
using namespace std;
template <typename HashedObj>
class HashTable
{
public:
explicit HashTable(int size = 101);
void makeEmpty()
{
for(int i = 0; i < theLists.size(); i++)
theLists[i].clear();
}
bool contains(const HashedObj & x) const
{
const list<HashedObj> & whichList = theLists[myhash(x)];
return find(whichList.begin(), whichList.end(), x) != whichList.end();
}
bool remove(const HashedObj & x)
{
list<HashedObj> & whichList = theLists[myhash(x)];
typename list<HashedObj>::iterator itr = find(whichList.begin(), whichList.end(), x);
if(itr == whichList.end())
return false;
whichList.erase(itr);
--currentSize;
return true;
}
bool insert(const HashedObj & x)
{
list<HashedObj> & whichList = theLists[myhash(x)];
if(find(whichList.begin(), whichList.end(), x) != whichList.end())
return false;
whichList.push_back(x);
if(++currentSize > theLists.size())
rehash();
return true;
}
private:
vector<list<HashedObj> > theLists; // The array of Lists
int currentSize;
void rehash()
{
vector<list<HashedObj> > oldLists = theLists;
// Create new double-sized, empty table
theLists.resize(2 * theLists.size());
for(int j = 0; j < theLists.size(); j++)
theLists[j].clear();
// Copy table over
currentSize = 0;
for(int i = 0; i < oldLists.size(); i++)
{
typename list<HashedObj>::iterator itr = oldLists[i].begin();
while(itr != oldLists[i].end())
insert(*itr++);
}
}
int myhash(const HashedObj & x) const
{
int hashVal = hash(x);
hashVal %= theLists.size();
if(hashVal < 0)
hashVal += theLists.size();
return hashVal;
}
};
2、使用探测法(probing hash tables)
template <typename HashedObj>
class HashTable
{
public:
explicit HashTable(int size = 101) : array(size)
{
makeEmpty();
}
void makeEmpty()
{
currentSize = 0;
for(int i = 0; i < array.size(); i++)
array[i].info = EMPTY;
}
bool contains(const HashedObj & x) const
{
return isActive(findPos(x));
}
bool insert(const HashedObj & x)
{
// Insert x as active
int currentPos = findPos(x);
if(isActive(currentPos))
return false;
array[currentPos] = HashEntry(x, ACTIVE);
if(++currentSize > array.size()/2)
rehash();
return true;
}
bool remove(const HashedObj & x)
{
int currentPos = findPos(x);
if(!isActive(currentPos))
return false;
array[currentPos].info = DELETED;
return true;
}
enum EntryType { ACTIVE, EMPTY, DELETED };
private:
struct HashEntry
{
HashedObj element;
EntryType info;
HashEntry(const HashedObj & e = HashedObj(), EntryType i = EMPTY )
: element(e), info(i) { }
};
vector<HashEntry> array;
int currentSize;
int findPos(const HashedObj & x) const
{
int offset = 1;
int currentPos = myhash(x);
while(array[currentPos].info != EMPTY && array[currentPos].element != x)
{
currentPos += offset; // Compute ith probe
offset += 2;
if(currentPos >= array.size())
currentPos -= array.size();
}
return currentPos;
}
bool isActive(int currentPos) const
{
return array[currentPos].info == ACTIVE;
}
void rehash()
{
vector<HashEntry> oldArray = array;
// Create new double-sized, empty table
array.resize(2*oldArray.size());
for(int j = 0; j < array.size(); j++)
array[j].info = EMPTY;
// Copy table over
currentSize = 0;
for(int i = 0; i < oldArray.size(); i++)
if(oldArray[i].info == ACTIVE)
insert(oldArray[i].element);
}
int myhash(const HashedObj & x) const;
};
作者:
阿凡卢
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。