哈希表的分离链接法其实就是个vector<type>容器 + 链表来实现的,其本质就是如果数值(mod)相等的话就插入到vector<type>的同一格,将相等的两个值依次存放在链表中,如果空间很小的话建议不要采用此方法,因为此方法的链表为双向链表,下面为分离链接法的代码:
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<list>
using namespace std;
template<typename HashedObj>
class HashTable
{
public:
explicit HashTable(int size = 101)
{
theLists.resize(size);
currentSize = size;
}
bool contains(const HashedObj & x) const;
void makeEmpty();
bool insert(const HashedObj & x);
bool remove(const HashedObj & x);
private:
vector<list<HashedObj> > theLists; // the array of Lists
int currentSize;
void rehash();
int myHash(const HashedObj &x) const;
};
class Employee
{
public:
const string &getName() const
{
return name;
}
bool operator== (const Employee &rhs) const
{
return getName() == rhs.getName();
}
bool operator!= (const Employee &rhs) const
{
return !(*this == rhs);
}
private:
string name;
double salary;
int senioity;
};
int hash(const string & key)
{
int hashVal = 0;
for(int i=0;i<key.length();i++)
{
hashVal = hashVal * 37 + key[i];
}
return hashVal;
}
int hash(int key)
{
return key;
}
int hash(const Employee & item)
{
return hash(item.getName());
}
bool Prime(int res) //散列表最好为素数
{
for(int i=2;i<res/2;i++)
{
if(res % i == 0)
{
return true;
break;
}
}
return false;
}
int nextPrime(int num)
{
while(1)
{
if(Prime(num) == false)
{
return num;
break;
}
else
{
num++;
}
}
}
template<typename HashedObj>
int HashTable<HashedObj>::myHash(const HashedObj & x) const
{
int hashVal = hash(x);
hashVal %= theLists.size(); //theLists.size()为总容量
if(hashVal < 0)
{
hashVal += theLists.size();
}
return hashVal;
}
template<typename HashedObj>
void HashTable<HashedObj>::rehash()
{
vector<list<HashedObj> > oldLists = theLists;
theLists.resize(nextPrime(2 * theLists.size()));
for(int j=0;j<theLists.size();j++)
{
theLists[j].clear();
}
cout<<theLists.size()<<endl;
currentSize = 0;
for(int i=0;i<oldLists.size();i++) //vector<>从上到下
{
typename list<HashedObj>::iterator itr = oldLists[i].begin(); //链表头到尾覆盖
while(itr != oldLists[i].end())
insert(*itr++);
}
}
template<typename HashedObj>
void HashTable<HashedObj>::makeEmpty()
{
for(int i=0;i<theLists.size();i++)
{
theLists[i].clear();
}
}
template<typename HashedObj>
bool HashTable<HashedObj>::contains(const HashedObj & x) const
{
const list<HashedObj> &whichList = theLists[myHash(x)];
return find(whichList.begin(),whichList.end(),x) != whichList.end();
}
template<typename HashedObj>
bool HashTable<HashedObj>::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;
}
template<typename HashedObj>
bool HashTable<HashedObj>::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;
}
int main()
{
HashTable<int> b;
b.insert(1);
b.insert(10);
b.insert(100);
b.insert(9);
b.insert(69);
b.insert(57);
if(b.contains(100) && b.contains(57))
{
cout<<"yes"<<endl;
}
else
{
cout<<"no"<<endl;
}
if(b.insert(57))
{
cout<<"insert succeed!"<<endl;
}
else
{
cout<<"repeat!"<<endl;
}
if(b.remove(69))
{
cout<<"remove succeed!"<<endl;
}
else
{
cout<<"The element not exist in HashTable";
}
b.makeEmpty();
if(b.contains(1) || b.contains(10) || b.contains(100))
{
cout<<"The HashTable is not empty!"<<endl;
}
else
{
cout<<"It is empty!"<<endl;
}
return 0;
}