介绍STL里hashtable的使用
例子:
#include<hash_set>
#include<iostream>
using namespace std;
int main()
{
hashtable<
int, //Value类型
hash<int>, //键值类型
identity<int>, //提取键值的方法
equal_to<int>, //判断相等的方法
alloc> //分配内存
iht(50, hash<int>(), equal_to<int>()); //声明iht变量并调用hashtable构造函数
iht.insert_unique(59);
iht.insert_unique(63);
//声明一个迭代器
hashtable<
int, /
int,
hash<int>,
identity<int>,
equal_to<int>,
alloc>
::iterator ite = iht.begin(); //hash table的迭代器是前向迭代器
for(int i = 0; i < iht.size(); ++i, ++ite)
{
cout<<*ite<<' ';
}
}
hash table的find函数和count函数:
iterator find(const key_type& key)
{
size_type n = bkt_num(key);
node* first;
//以下,从bucket list从头开始对比,对比相同就返回
for (first = buckets[n];
first && !equals(get_key(first->val), key);
first = first->next)
{}
return iterator(first, this);
}
size_type count(const key_type& key) const
{
const size_type n = bkt_num_key(key);
size_type result = 0;
//以下,从bucket list的头开始,一一对比每个元素的键值。对比成功就+1
for(const node* cur = buckets[n]; cur; cur = cur->next)
{
if(equals(get_key(cur->val),key))
{
++result;
}
}
return result;
}
hash function
<stl_hash_fun.h>定义有数个现成的hash function,全都是仿函数。先前谈到hash function是用来计算元素位置的。针对char,int,long这些类型,hash function什么也没做,只是返回了原值。但对于字符串const char*,就设计了如下转换函数:
template<class key> struct hash{};
inline size_t __stl_hash_string(const char* s)
{
unsigned long h = 0;
for(;*s;++s)
h = 5*h + *s;
return size_t(h);
}
//特化 STL的hash function还是挺简单的,直接返回值,仅仅处理了类型,返回一个可mod的值
//STL无法处理上述列出的各类型意外的元素,例如string,double等等,用户需要自定义自己的hashfunction
_stl_template_null struct hash<char*>
{ size_t operator()(const char* s) const { return _stl_hash_string(s);}};//重载了()
_stl_template_null struct hash<const char*>
{ size_t operator()(const char* s){ return _stl_hash_string(s);}};
_stl_template_null struct hash<char>
{ size_t operator()(char x) const {return x}};
_stl_template_null struct hash<unsigned char>
{ size_t operator()(unsigned int) const{return x;}};
_stl_template_null struct hash<signed char>
{ size_t operator()(unsigned char)const {return x;}}
..........
上面代码表明,STL无法处理上述所列各项形别以外的元素,例如string,double等等。欲处理这些,用户必须自定义自己的hash function。
hash_set
虽然STL只规范复杂度和接口,并不规范实现方法,但STL set多以RB-tree为底层机制。SGI则是在STL标志规格之外又提供了一个所谓的hash_set,以hashtable为底层机制。由于hash_set所提供的操作接口,hashtable都提供了,所以几乎所有hash_set的操作行为,都只是转调了hashtable的操作行为而已。下面是hash_set的代码摘录:
template<
class Value,
class HashFunc = hash<Value>,
class EqualKey = equal_to<Value>,
class Alloc = alloc>
class hash_set
{
private:
typedef hashtable<Value, Value, HashFunc, identity<Value>, EqualKey, Alloc> ht;
ht rep; //底层是以hash table 完成
public:
typedef typename ht::key_type key_type; //typename是告知编译器这是类型不是static变量
typedef typename ht::value_type value_type;
typedef typename ht::hasher hasher;
typedef typename ht::key_equal key_equal;
typedef typename ht::size_type size_type;
typedef typename ht::difference_type difference_type;
typedef typename ht::const_pointer pointer;
typedef typename ht::const_pointer const_pointer;
typedef typename ht::const_reference reference;
typedef typename ht::const_reference const_reference;
typedef typename ht::const_iterator iterator;
typedef typename ht::const_iterator const_iterator;
hasher hash_funct() const{ return rep.hash_funct();}
key_equal key_eq() const {return rep.key_eq();}
public:
hash_set():rep(100, hasher(), key_equal()){}
explict hash_set(size_type n): rep(n, hasher(), key_equal()){}
hash_set(size_type n, const hasher& hf):rep(n, hf, key_equal()){}
hash_set(size_type n, const hasher& hf, const key_equal& eql):rep(n, hf, eql){}
template<class InputIteratir>
hash_set(InputIterator f, InputIterator l):rep(100, hasher(), key_equal())
{ rep.insert_unique(f,l);}
template<class InputIterator>
hash_set(InpurIterator f, InputIterator l, size_type n):rep(n, hasher(),key_equal())
{ rep.insert_unique(f,l);}
.......//省略成吨的构造函数
public:
size_type size() const{ return rep.size();}
size_type max_size() const { return rep.max_size();}
bool empty() const { return rep.empty();}
void swap(hash_set& hs) { rep.swap(hs.rep);}
friend bool operator== __STL_NULL_TMPL_ARGS(const hash_set&, const hash_set&);
iterator begin() const { return rep.begin();}
iterator end() const {return rep.end();}
.....//省略成吨的接口函数
};
总结:
如上便是SGI STL实现hash table以及对接STL标准的代码和一些注释,还是一如既往的朴素而高效。