1 #include <vector> 2 #include <list> 3 #include <string> 4 #include <algorithm> 5 using std::vector; 6 using std::list; 7 using std::string; 8 using std::find; 9 10 int hash(const string &key) 11 { 12 int hashVal = 0; 13 14 for(string::size_type i=0; i!=key.size(); ++i) 15 hashVal += key[i]; 16 17 return hashVal; 18 } 19 int hash(int key) 20 { 21 return key; 22 } 23 24 template<typename HashedObj> 25 class HashTable 26 { 27 public: 28 explicit HashTable(int size=101):theLists(size) {} 29 30 bool contains(const HashedObj &x) const 31 { 32 const list<HashedObj> &whichList = theLists[myhash(x)]; 33 return find(whichList.begin(), whichList.end(), x)!=whichList.end(); 34 } 35 void clear() 36 { 37 for(int i=0; i<theLists.size(); ++i) 38 theLists[i].clear(); 39 } 40 bool insert(const HashedObj &x) 41 { 42 const list<HashedObj> &whichList = theLists[myhash(x)]; 43 44 if(find(whichList.begin(), whichList.end(), x)!=whichList.end()) 45 return false; 46 47 whichList.push_front(x); 48 ++currentSize; 49 return true; 50 } 51 bool remove(const HashedObj &x) 52 { 53 const list<HashedObj> &whichList = theLists[myhash(x)]; 54 list<HashedObj>::iterator it = find(whichList.begin(), whichList.end(), x); 55 56 if(it==whichList.end()) 57 return false; 58 59 whichList.erase(it); 60 --currentSize; 61 return true; 62 } 63 64 private: 65 vector<list<HashedObj> > theLists; 66 int currentSize; 67 68 int myhash(const HashedObj &x) const 69 { 70 int hashVal = hash(x); 71 72 hashVal %= theLists.size(); 73 if(hashVal<0) 74 hashVal += theLists.size(); 75 76 return hashVal; 77 } 78 };
以上是分离链接法的C++实现。
除了分离链接法以外,还有一些不使用链表的实现散列表的方法,包括线性探测、平方探测、双散列等。
使用分离链接法,当出现冲突时,直接将新元素插入对应链表即可。不使用链表时,可采用线性探测、平方探测、双散列等技术来处理冲突。
线性探测&平方探测:h(x) = hash(x)+f(i),其中f(i)分别是i的一次和二次函数。
双散列:h(x) = hash1(x)+f(i)*hash2(x)。
另外,宜使散列表大小为素数值,从而使hash值分布更均匀,以减少冲突。