hash_set,hash_map,hash_multiset,hash_multimap

来源:互联网 发布:cocos2d x js 编辑:程序博客网 时间:2024/06/06 02:33

上面四中容器都基于hashtable这种底层的机制。二叉搜索树具有对数平均时间的表现,但这样的表现简历在输入数据有足够的随机性这一假设上。而hashtable这一数据结构在插入,删除,搜寻等操作上都具有“常数平均时间”,而且这种表现不依赖输入元素的随机性。

在STL中hashtable的实现是使用开链法去解决不同元素落在同一个存储单元中。这种做法是在每一个表格元素中维护一个list,然后我们在那个list身上执行元素的插入、搜寻、删除等操作。


如上图,在STL中,hash表中的元素使用一个vector来表示,而vector中的每个元素都是一个list的头指针。list中的元素真正存放了插入的元素。

在STL的实现中,用质数来设计表格vector的大小,先将28个质数(大约呈现两倍的关系)计算好备用。53,97,193,389,769..........4294967291。当初始化时,hashtable选择一个大于初始化数据的最小质数作为vetor的大小。那么当插入的个数增加,可能需要将vector的容量增加,在STL中这个判断原则比较特殊:当插入了一个新的数据之后,若在这个list上的数据个数大于了vector当前的元素个数,那么就需要进行重建,选下一个质数为vector的大小,再将原来的数据重新计算放入新的hashtable

插入数据分为两种,一种是允许重复,另一种是不允许重复。如果是不允许重复,定位到确定的list之后,需要遍历该list查看该键值是否已经存在,若不存在则插入,否则直接返回。若允许重复,还是需要检查,如果之前键值存在,那么存放在该键值之后,若不存在放在该list的头部。(原因不详)

在hash functions中我们要将输入的值进行操作输出一个可以进行模运算的值。对于大多数的类型,hash function什么也没做,只是忠实的返回了原值,但是对于字符串char*,设计了一个转换函数

size_t __stl_hash_string(const char *s)

{

unsigned long h = 0;

for(; *s;++s)

h = 5*h + *s;

return size_t(h);

}

这里为什么用5这个值原因不明。

有了hashtable的底层实现,hash_set, hash_map,hash_multi_set, hash_multimap就不难理解了,这四种容器都是使用了hashtable的机制实现,set和map的区别是set只有一个键值,map有一个键值和一个实值,按照键值进行hash,实值可以修改。multi和没有multi的区别就是是否允许重复的键值出现。


0 0
原创粉丝点击