数据结构-散列表
程序员文章站
2024-03-16 15:38:46
...
数据结构-散列表
两个重要的问题:
-
散列函数
-
散列冲突
-
- 散列函数的选择,使得尽可能少的发生散列冲突;
- 标准的散列关键字是正整数,散列函数可能是整数除以散列表的大小取余;
- 散列表的大小一般是素数,散列分布的更加均匀;
- 如果关键字是字符串的话,散列函数可以是把字符串的所有ascII码加起来;
几个散列函数
int hashs1(const string & key, int tablesize){
int hashval{0};
for(char x:key){
hashval+= x;
}
return hashval%tablesize;
}
int hashs2(const string& key, int tablesize){
return (key[0]+27*key[1]+729*key[2])%tablesize;
}
int hashs3(const string& key, int tablesize){
unsigned int hashval{0};
for(char ch:key){
hashval=37*hashval+ch;
}
return hashval%tablesize;
}
如何解决散列冲突
分离链接法
将散列到同一个值的所有元素保存到一个链表中。一个典型的分离链接法哈希表
template<typename HashedObj>
class HashTable{
public:
explicit HashTable(int size=101);
bool contains(const HashedObj& x) const;
void makeEmpty();
bool insert(const HashedObj& x);
bool insert(HashedObj&& x);
bool remove(const HashedObj& x);
private:
vector<list<HashedObj>> theList;
int currentSize;
void rehash();
size_t myhash(const HashedObj& x);
};
template<typename HashedObj>
void HashTable<HashedObj>::makeEmpty(){
for(auto& thisList:theList)
thisList.clear();
}
template <typename HashedObj>
bool HashTable<HashedObj>::contains(const HashedObj& x){
auto & whichList = theList[myhash(x)];
return find(begin(whichList), end(whichList), x) != end(whichList);
}
template<typename HashedObj>
bool HashTable<HashedObj>::remove(const HashedObj& x){
auto& whichList = theList[myhash(x)];
auto itr = find(begin(whichList), end(whichList),x);
if(itr == end(whichList)) return false;
whichList.erase(itr);
--currentSize;
return true;
}
template<typename HashedObj>
bool HashTable<HashedObj>::insert(const HashedObj& x){
auto & whichList = theList[myhash(x)];
if(find(begin(whichList),end(whichList),x) != end(whichList())) return false;
whichList.push_back(x);
if(++currentSize > theList.size())
rehash();
return true;
}
上一篇: 数据结构之散列表
下一篇: 判断位置是否会发生碰撞