boost unordered中桶个数
来源:互联网 发布:c语言大型程序源代码 编辑:程序博客网 时间:2024/06/05 00:37
本文接着 http://blog.csdn.net/freemannnn/article/details/24546963 继续讨论。
桶的初始个数
在boost头文件boost\unordered\detail\util.hpp中定义了桶的初始数目:
static const std::size_t default_bucket_count = 11;
也就是说,一个unordered中,即使没有元素,桶的个数至少也是default_bucket_count。
影响桶的个数的因素
首先,桶的个数是根据需要实时变化的。在unordered中元素个数一定的情况下,如果桶的个数过少,就会导致每个桶中的元素个数过多,从而使查找效率低下;如果桶的个数过多,就会导致很多桶都是空的,从而使内存利用率低下。因此,动态的选取一个合适桶的个数很关键。
影响它的因素有:
1. X(size_type n)
Construct an empty container with at least n buckets (X is the container type).
unordered的构造函数,n直接指定了桶的个数。
2. X(InputIterator i, InputIterator j, size_type n)
Construct an empty container with at least n buckets and insert elements from the range [i, j) (X is the container type).
unordered的构造函数,n直接指定了桶的个数。
3. void rehash(size_type n)
Changes the number of buckets so that there at least n
显式调用rehash函数(很多情况下,此函数被其它函数调用,这种情况称隐式调用),n直接指定了桶的个数。
4. float max_load_factor(float z)
Changes the container's maximum load factor, using z as a hint
改变最大负载因子(请注意仅仅是提示,如果最大负载因子z不太合理,即过大或过小,可能导致设置失败)。max_load_factor默认值为1.0(boost\unordered\detail\table.hpp文件中table类的构造函数中初始化了此值),可以由用户设置。
unordered内部维护一个不变式:load_factor <= max_load_factor
负载因子load_factor可以通过调用float load_factor() const获取,它的定义是The average number of elements per bucket,即unordered中元素个数 / unordered中桶的个数。过大的负载因子会导致查找速度变慢,过小的负载因子会导致内存空间的严重浪费。
如果改变max_load_factor导致上述不变式不成立(load_factor > max_load_factor),这时候unordered内部就会自动调用rehash以增加桶的个数,从而使load_factor减小,最终保证不变式成立。
5. 其他导致unordered中元素个数变化函数(insert,erase等操作)
unordered中元素个数变化,导致上述不变式不成立,以后操作同情形4。
桶的个数是如何变化的。
当桶的个数m发生变化后,原来的哈希表就失效了。
举个例子:
原来桶的个数m为11, 哈希值为25的元素,存放在第3号桶中。
现在桶的个数m变为19,哈希值为25的元素,存放在第6号桶中。
所以当桶的个数发生变化后,整个哈希表就要重新构造了。这个代价是非常大的。为此,unordered内部实现采取了措施以避免桶的个数发生变化的频率过高。使用的方法和vector一样,每次分配足够多的桶。当上次分配的桶不够用了后,下次分配更多的桶。以下是桶分配的个数的列表(这个列表可以在boost\unordered\detail\util.hpp中找到):
#define BOOST_UNORDERED_PRIMES \
(17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
(97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \
(1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \
(49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \
(1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul) \
(50331653ul)(100663319ul)(201326611ul)(402653189ul)(805306457ul) \
(1610612741ul)(3221225473ul)(4294967291ul)
http://blog.csdn.net/freemannnn/article/details/24546963 当初始桶个数default_bucket_count=11不够时,就分配17个桶,再不够了,就分配29个桶,以此类推(为什么桶的个数是素数,请参http://blog.csdn.net/freemannnn/article/details/24546963)。
下面更细节的讨论unordered中重新选择桶的个数。
当向unordered中增加若干元素以至于当前load_factor大于max_load_factor时(并不是每次增加元素都会导致load_factor大于max_load_factor),就会重新选择桶的个数。
选择的方法是:
1. 先计算当前最少应该需要的桶个数
min_bucket_count = element_count / max_load_factor
其中element_count是unordered当前元素个数,max_load_factor是最大负载因子。
2. 在BOOST_UNORDERED_PRIMES列表中找到比min_bucket_count大的最小元素(也就是BOOST_UNORDERED_PRIMES列表中比min_bucket_count刚好大一点点的元素,比如min_bucket_count是23,那么找到的元素是29ul),这个元素即是新的桶的个数。这个选择过程由boost\unordered\detail\util.hpp头文件中的next_prime函数实现。
以下是这个函数的实现细节:
template<class T>
struct prime_list_template
{
static std::size_t const value[];
static std::ptrdiff_t const length;
};
// 定义了桶个数数组
// BOOST_PP_SEQ_ENUM宏参见 http://blog.csdn.net/freemannnn/article/details/24531547
template<class T>
std::size_t const prime_list_template<T>::value[] =
{ BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIMES) };
// 定义了桶个数数组元素的个数
// BOOST_PP_SEQ_SIZE 宏参见 http://blog.csdn.net/freemannnn/article/details/24528959
template<class T>
std::ptrdiff_t const prime_list_template<T>::length =
BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
// 为什么用prime_list_template模板,然后实例化一个prime_list,可能是不想将prime_list_template的value和length成员放在源文件中(非模板类的静态数组成员的定义必须放在源文件中,模板类有这个特权)
typedef prime_list_template<std::size_t> prime_list;
// 以下是二分查找的过程
inline std::size_t next_prime(std::size_t num)
{
std::size_t const* const prime_list_begin = prime_list::value;
std::size_t const* const prime_list_end = prime_list_begin + prime_list::length;
std::size_t const* bound = std::lower_bound(prime_list_begin, prime_list_end, num);
if(bound == prime_list_end)
bound--;
return *bound;
}
- boost unordered中桶个数
- boost unordered 初识
- boost unordered map 小试
- unordered
- boost.unordered 基于hash table的四种容器(即hash_map,unordered_mutimap,hash_set,hash_multiset)
- unordered学习(c++11)
- CF 27C Unordered Subsequence
- vs2005中安装boost
- vs2005中安装boost
- vs2010中引入boost
- liunx中boost安装
- boost中unorder_set使用
- 【Boost】boost库中sleep方法详解
- 【Boost】boost库中timer定时器
- 【Boost】boost库中function的用法
- 【Boost】boost库中bind的用法
- 【Boost】boost库中智能指针概述
- 数据库中session个数
- 判断NSNUll不崩溃高大上的方法
- 线段树入门 单点更新 hdu 1751 I Hate It hdu 1166 敌兵布阵
- 点击主界面 PopupMenu消失
- 备忘录:javascript通过url向jsp页面传递中文参数乱码解决方法
- [leetcode] string to integer
- boost unordered中桶个数
- 用opencv实现立体匹配
- mysql 引擎
- 课程设计一
- C#处理Json数据
- JAVA中的抽象类
- 需求文档测试
- [Oracle]获取执行计划的各个方法总结
- Hibernate--Session