選擇鍵值,沖突的時候采取不同的政策
散列函數:
簡單的散列函數:
1 int hash(const string & key,int tableSize)
2 {
3 int hashVal = 0;
4 for(int i = 0; i < key.length();++i)
5 {
6 hashVal + = key[i];
7 }
8 return hashVal % tableSize;
9 }
比較好的散列函數:
1 int hash( const string & key,int tableSize )
2 {
3 int hashVal = 0;
4 for(int i = 0; i <key.length();++i)
5 {
6 hashVal = 37*hashVal + key[i];
7 }
8 hashVal %= tableSize;
9 if(hashVal < 0)
10 hashVal +=tableSize;
11
12 return hashVal;
13 }
鍵的長度和性質 影響選擇。
分離連結法
分離連結散清單的類構架
1 template <typename HashedObj>
2 class HashTable
3 {
4 public:
5 explicit HashTable( int size = 101);
6 bool contains (const HashedObj & x) const;
7 void makeEmpty();
8 void insert(const HashedObj & x);
9 void remove(const HashedObj & x);
10 private:
11 vector<list<HashedObj> > theLists;
12 int currentSize;
13 void rehash();
14 int myhash( const HashedObj & x) const;
15 };
16 int hash(const string & key);
17 int hash(int key);
散清單myhash的成員函數:
1 int myhash(const HashedObj & x) const
2 {
3 int hashVal = hash(x);
4 hashVal %= theLists.size();
5 if(hashVal < 0)
6 hashVal += theLists.size();
7 return hashVal;
8 }
使用name成員為鍵,提供的散列函數執行個體:
1 class Employee
2 {
3 public:
4 const string & getName() const
5 {
6 return name;
7 }
8 bool operator==( const Employee & rhs ) const
9 {
10 return getName() == rhs.getName();
11 }
12 bool operator!=(const Employee & rhs) const
13 {
14 return !(*this == rhs);
15 }
16 private:
17 string name;
18 double salary;
19 int seniority;
20 };
21 int hash(const Employee & item)
22 {
23 return hash(item.getName());
24 }
實作makeEmpty contains remove:
1 void makeEmpty()
2 {
3 for(int i =0;i<theLists.size();i++)
4 theLists[i].clear();
5 }
6 bool contains(const HashedObj & x) const
7 {
8 const list<HashedObj> & whichList = theLists[myhash(x)];
9 return find(whichList.begin(),whichList.end(),x)!=whichList.end();
10 }
11 bool remove(const HashedObj & x) const
12 {
13 list<HashedObj> & whichList = theLists[myhash(x)];
14 list<HashedObj>::iterator itr = find(whichList.begin(),whichList.end(),x);
15
16 if(itr == whichList.end())
17 return false;
18
19 whichList.erase(itr);
20 --currentSize;
21 return true;
22 }
分離散清單的insert執行個體
1 bool insert(const HashedObj & x)
2 {
3 list<HashedObj> & whichList = theLists[myhash(x)];
4 if(find(whichList.begin(),whichList.end(),x)!=whichList.end())
5 return false;
6 whichList.push_back(x);
7 if(++currentSize > theLists.size())
8 rehash();
9
10 return true;
11 }
裝填因子:散清單中的元素個數 與 散清單大小的 比值
執行一次查找所需的時間:計算散列函數值所需要的常數時間加上周遊表所用的時間
不使用連結清單的散清單:
當沖突發生時,直接尋找下一單元
<線性探測>
<平方探測>
使用探測政策的散清單的類接口
1 template <typename HashedObj>
2 class HashedObj
3 {
4 public:
5 explicit HashTable(int size = 101);
6 bool contains(const HashedObj & x) const;
7 void makeEmpty();
8 bool insert(const HashedObj & x);
9 bool remove(const HashedObj & x);
10 enum EntryType{ACTIVE,EMPTY,DELETED};
11 private:
12 struct HashEntry
13 {
14 HashedObj element;
15 EntryType info;
16
17 HashEntry(const HashedObj & e = HashedObj(),EntryType i = EMPTY):element(e),info(i){}
18 };
19 vector<HashEntry> array;
20 int currentSize;
21 bool isActive(int currentPos) const;
22 int findPos(const HashedObj & x) const;
23 void rehash();
24 int myhash(const HashedObj & x) const;
25 };
初始化平方探測散清單
1 explicit HashTable(int size = 101):array(nextPrime(size))
2 {
3 makeEmpty();
4 }
5 void makeEmpty()
6 {
7 currentSize = 0;
8 for(int i = 0 ; i < array.size(); i++)
9 array[i].info = EMPTY;
10 }
使用平方探測進行散列的contains findPos isActive
1 bool contains(const HashedObj & x) const
2 {
3 return isActive(findPos(x));
4 }
5 int findPos(const HashedObj & x) const
6 {
7 int offset = 1;
8 int currentPos = myhash(x);
9
10 while(array[currentPos].info != EMPTY && array[currentPos].element != x)
11 {
12 currentPos += offset;
13 offset += 2;
14 if(currentPos >= array.size())
15 currentPos -= array.size();
16 }
17 return currentPos;
18 }
19 bool isActive(int currentPos) const
20 {
21 return array[currentPos].info == ACTIVE;
22 }
使用平方探測的insert remove
bool insert( const HashedObj & x)
{
int currentPos = findPos(x);
if(isActive( currentPos ))
return false;
array[currentPos] = HashEntry(x,ACTIVE);
if(++currnetSize>array.size()/2)
rehash();
}
bool remove(const HashedObj & x)
{
int currentPos = findPos(x);
if(!isActive(currentPos))
return false;
array[currentPos].info = DELETED;
return true;
}
<雙散列>
對分離散清單的再散列
1 void rehash()
2 {
3 vector<HashEntry> oldArray = array;
4 array.size(nextPrime(2*oldArray.size()));
5 for(int j = 0; j < array.size(); j++)
6 {
7 array[j].info = EMPTY;
8 }
9 currentSize = 0;
10 for(int i = 0; i < array.size(); i++)
11 {
12 if(oldArray[i].info == ACTIVE)
13 insert(oldArray[i].element);
14 }
15 }
對探測散清單的再散列
1 void rehash()
2 {
3 vector<list<HashedObj> > oldLists = theLists;
4 theLists.resize( nextPrime( 2*theLists.size() ) );
5 for(int j = 0; j < theLists.size(); j++)
6 {
7 theLists[j].clear();
8 }
9 currentSize = 0;
10 for(int i = 0; i < oldLists.size(); i++)
11 {
12 list<HashedObj>::iterator itr = oldLists[i].begin();
13 while( itr != oldLists[i].end( ) )
14 insert(*itr++);
15 }
16 }
作者:xingoo