sgi的hashtable

与hashtable,hash_set,hash_multiset,hash_map,hash_multimap相关的头文件有stl_hashtable.h,stl_hash_fun.h,hash_set,hash_map。
stl_hashtable.h中定义了hashtable,stl_hash_fun.h定义了常见类型的hash函数,hash_set中定义了hash_set和hash_multiset,hash_map中定义了hash_map和hash_multimap。

stl_hash_fun.h里定义了常见整型的hash函数,不过只是简单的返回它们本身的值而已;还定义了字符串的hash函数。
除此之外的其他类型,都需要自行定义hash函数,如果对本文件提供的hash函数不满意,也可以自行定义。

template <typename 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);
}

template<> struct hash<char*>
{
    size_t operator()(const char* s) const
    { return __stl_hash_string(s); }
};

template<> struct hash<const char*>
{
    size_t operator()(const char* s) const
    { return __stl_hash_string(s); }
};

template<> struct hash<char>
{
    size_t operator()(char x) const
    { return x; }
};
template<> struct hash<unsigned char>
{
    size_t operator()(unsigned char x) const
    { return x; }
};
template<> struct hash<signed char>
{
    size_t operator()(unsigned char x) const
    { return x; }
};

template<> struct hash<short>
{
    size_t operator()(short x) const
    { return x; }
};
template<> struct hash<unsigned short>
{
    size_t operator()(unsigned short x) const
    { return x; }
};

template<> struct hash<int>
{
    size_t operator()(int x) const
    { return x; }
};
template<> struct hash<unsigned int>
{
    size_t operator()(unsigned int x) const
    { return x; }
};

template<> struct hash<long>
{
    size_t operator()(long x) const
    { return x; }
};
template<> struct hash<unsigned long>
{
    size_t operator()(unsigned long x) const
    { return x; }
};
sgi以开链法完成hashtable, 称hashtable的数组为buckets, 以std::vector完成, buckets vector每个元素的类型是指向节点的指针.

如何确定节点在哪个bucket?
先对Key取hash后, 再执行"hash值%vector的大小"获得其bucket.
关于buckets vector的大小, sgi内部定义了一个拥有28个元素的整型数组, 存储了28个质数, 这些质数逐渐呈现大约两倍的关系, 最小的质数是53, hashtable自动将大小提升为最接近且足够容纳所有节点的质数. 这样设计保证了hashtable足够稀疏.
// 迭代器内有一个指向节点的指针, 一个指向hashtable的指针.
// 这是它的自加操作, 并不提供自减操作:
iterator& operator++()
{
    const _Node* __old = _M_cur;
    _M_cur = _M_cur->_M_next; // 链表的下一个节点
    if(!_M_cur) // 链表如已到结尾, 则要在vector里跳到下一个bucket
    {
        // 获得原节点所在的bucket
        size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
        // 当找到下一节点结束
        // 或后面的bucket空无一物时也结束, 此时_M_cur为空, 迭代器与end()相等
        while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
            _M_cur = _M_ht->_M_buckets[__bucket];
    }
    return *this;
}

// hashtable理解起来并不困难, 我也懒得去标注源代码了.

hash_set和hash_map缺省使用大小为100的表格,hashtable将调整为193。

你可能感兴趣的:(sgi的hashtable)