散列之分离链接法

 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值分布更均匀,以减少冲突。

posted @ 2015-07-15 11:29  __brthls  阅读(245)  评论(0编辑  收藏  举报