前言
前面介绍的关联容器set、multiset、map和multimap的底层机制都是基于RB-Tree红黑树,虽然能够实现在插入、删除和搜素操作能够达到对数平均时间,可是要求输入数据有足够的随机性。本文介绍的hash table不需要要求输入数据具有随机性,在插入、删除和搜素操作都能达到常数平均时间。本文介绍的hash table是来自SGI STL中的<stl_hashtable.h>文件,在这里为了避免冲突(即不同元素映射到相同的键值位置),采用了拉链法来解决冲突问题。SGI中实现hash table的方式,在每个表格元素中维护一个链表, 然后在链表上执行元素的插入、搜寻、删除等操作,该表格中的每个元素被称为桶(bucket)。有关hash table的介绍可往前面博文《散列表》查看。
hashtable散列表源码剖析
#ifndef __SGI_STL_INTERNAL_HASHTABLE_H
#define __SGI_STL_INTERNAL_HASHTABLE_H
// Hashtable class, used to implement the hashed associative containers
// hash_set, hash_map, hash_multiset, and hash_multimap.
//SGI STL的hashtable的实现方法是拉链法.
//拉链法可以避免hashtable的冲突问题,即不同数据映射到同一的hash值
//有关hashtable的介绍见前文:
//http://blog.csdn.net/chenhanzhun/article/details/38091431
#include <stl_algobase.h>
#include <stl_alloc.h>
#include <stl_construct.h>
#include <stl_tempbuf.h>
#include <stl_algo.h>
#include <stl_uninitialized.h>
#include <stl_function.h>
#include <stl_vector.h>
#include <stl_hash_fun.h>
__STL_BEGIN_NAMESPACE
//hashtable中链表的节点结构
//类似于单链表的节点结构
template <class _Val>
struct _Hashtable_node
{
_Hashtable_node* _M_next;//指向下一节点
_Val _M_val;//节点元素值
};
//这里使用前置声明, 避免在后面交叉引用会导致编译错误
template <class _Val, class _Key, class _HashFcn,
class _ExtractKey, class _EqualKey, class _Alloc = alloc>
class hashtable;
template <class _Val, class _Key, class _HashFcn,
class _ExtractKey, class _EqualKey, class _Alloc>
struct _Hashtable_iterator;
template <class _Val, class _Key, class _HashFcn,
class _ExtractKey, class _EqualKey, class _Alloc>
struct _Hashtable_const_iterator;
//hashtable迭代器定义
//注意:hash table迭代器没有提供后退操作operator--
//也没用提供逆向迭代器reverse iterator
template <class _Val, class _Key, class _HashFcn,
class _ExtractKey, class _EqualKey, class _Alloc>
struct _Hashtable_iterator {
//内嵌类型别名
typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
_Hashtable;
typedef _Hashtable_iterator<_Val, _Key, _HashFcn,
_ExtractKey, _EqualKey, _Alloc>
iterator;
typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
_ExtractKey, _EqualKey, _Alloc>
const_iterator;
typedef _Hashtable_node<_Val> _Node;
typedef forward_iterator_tag iterator_category;//采用正向迭代器
typedef _Val value_type;
typedef ptrdiff_t difference_type;
typedef size_t size_type;
typedef _Val& reference;
typedef _Val* pointer;
_Node* _M_cur;//当前迭代器所指位置
_Hashtable* _M_ht;//hashtable中的位置,控制访问桶子连续性
_Hashtable_iterator(_Node* __n, _Hashtable* __tab)
: _M_cur(__n), _M_ht(__tab) {}
_Hashtable_iterator() {}
//返回当前节点元素值的引用
reference operator*() const { return _M_cur->_M_val; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
//操作符重载定义在后面定义
iterator& operator++();
iterator operator++(int);
//比较两个迭代器是否指向同一个节点
bool operator==(const iterator& __it) const
{ return _M_cur == __it._M_cur; }
bool operator!=(const iterator& __it) const
{ return _M_cur != __it._M_cur; }
};
//下面是const iterator的定义,基本和上面相同
template <class _Val, class _Key, class _HashFcn,
class _ExtractKey, class _EqualKey, class _Alloc>
struct _Hashtable_const_iterator {
typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
_Hashtable;
typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
_ExtractKey,_EqualKey,_Alloc>
iterator;
typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
_ExtractKey, _EqualKey, _Alloc>
const_iterator;
typedef _Hashtable_node<_Val> _Node;
typedef forward_iterator_tag iterator_category;
typedef _Val value_type;
typedef ptrdiff_t difference_type;
typedef size_t size_type;
typedef const _Val& reference;
typedef const _Val* pointer;
const _Node* _M_cur;
const _Hashtable* _M_ht;
_Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
: _M_cur(__n), _M_ht(__tab) {}
_Hashtable_const_iterator() {}
_Hashtable_const_iterator(const iterator& __it)
: _M_cur(__it._M_cur), _M_ht(__it._M_ht) {}
reference operator*() const { return _M_cur->_M_val; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
const_iterator& operator++();
const_iterator operator++(int);
bool operator==(const const_iterator& __it) const
{ return _M_cur == __it._M_cur; }
bool operator!=(const const_iterator& __it) const
{ return _M_cur != __it._M_cur; }
};
// Note: assumes long is at least 32 bits.
// 注意:假设long至少为32-bits, 可以根据自己需要修改
//定义28个素数用作hashtable的大小
enum { __stl_num_primes = 28 };
static const unsigned long __stl_prime_list[__stl_num_primes] =
{
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul
};
//返回大于n的最小素数
inline unsigned long __stl_next_prime(unsigned long __n)
{
const unsigned long* __first = __stl_prime_list;
const unsigned long* __last = __stl_prime_list + (int)__stl_num_primes;
const unsigned long* pos = lower_bound(__first, __last, __n);
/*
上面的lower_bound调用的是STL中的算法lower_bound();
该算法的功能:
Returns an iterator pointing to the first element in the range [first,last) which does not compare less than val.
The elements in the range shall already be sorted according to this same criterion (operator< or comp)
即返回在[first,last)范围内第一个不小于val的位置
注意:调用该算法之前,[first,last)范围里面的元素必须已排序
该算法的原型如下:
第一个版本:采用默认比较准则operator<
template <class ForwardIterator, class T>
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,
const T& val);
第二版本:采用用户指定的比较函数comp
te