您的位置:首页 > 其它

vector ,hashtable ,hashset 和 hashtable

2015-08-20 11:04 295 查看
说明:下文中的所谓的优缺点只不过算作一个分隔符,其实只有使用场景的不同,没有孰优孰劣。
vector:

【实现】vector的底层就是一个数组,所以其才能有O(1)的查找效率。只不过它是变长的,容量到达end_of_storage时便另寻空间自动扩容一倍,并将原来的数据都拷贝到新空间,之后将原来空间销毁。由于其数组的特性,决定了vector的频繁插入和删除的效率比较低。
【优点】查找效率高。
【缺点】除了查找,其他的效率都不特别高。
【其他】1,在优点和缺点这方面,list和queue简直是和vector形成了互补,所以在合适的应用场景下要选择合适的容器;
2,vector的iterator不仅重载了++,--,而且重载了*(前置)和==,这种重载更多的是考虑了vector存储对象的多样性,方便使用自定义对象。

hashtable:
【实现】C++的hashtable和普通的hashtable并没有什么区别,在防止冲突上采用的还是拉链法。其底层实现是vector+linkedlist,其每一个bucket就是一个vector,vector中存放的是linkedlist,不过这里的linkedlist并不是STL中的list或slist,而是自己维护的hash table node。
【优点】hashtable的优点就不用说了。
【缺点】hashtable的一个很重要的问题就是rehashing,如果数据量足够大,hashtable的空间总是会用完,那么就需要rehashing了,rehashing是非常浪费时间的,参考vector的扩容。例如, 在PHP中大型网站使用Memcached,它就是一个内存中很大的hashtable,里面存储着各种各样的数据,所以在rehashing时就会浪费很多时间并在此时间内拒绝访问。这样就会增加数据库的压力,甚至让网站不堪重负的down掉。所以,要么一开始就将Memcached设置到可用内存的上限,要么将不用继续提供的数据从Memcached中覆盖或清除掉。或者.....不向其中加入那么多的数据。
【其他】1,在防止冲突上除了线性探测和二次探测之外,还可以使用二重散列和多重散列,其目的都是尽可能将插入的数据比较均匀的存放在hashtable的内存空间内,防止冲突。
2,防止冲突,就一定要用到hashfunc,好的hashfunc会尽力做到上文第一点提到的结果。这里有一个Apache底层hashtable的hashfunc,参考如下:


//这是一个Apache底层的一个hashfunc,Magic Number 33,33只是试验得出的而已


//这里以一个string为例,将字符串中的每一个字母转换成33进制,然后对hashtable取模运算

int hashfunc(String key){
int sum=0;
for(int i=0;i<key.length();++i){
  sum=sum*33+(int)(key.charAt(i));
  sum=sum % HASH_TABLE_SIZE;
}
return sum;
}


hash_set:
hash_set和set的使用方式是一样的,只不过,其底层是实现机制不一样。
【实现】set多半是以RB-tree来实现的,而hash_set只是转而调用了hashtable的操作。使用set是为了快速查找元素,RB-tree和hashtable都能满足这个要求,只是RB-tree不允许数据重复,且set能根据键值自动排序。set其实就是一个键值和实值都一样的hashtable。
【优点】就是查找。
【缺点】hash_set的查找效率比set高,不过它不具有基于RB-tree set的其他性质。
【其他】hash_set和hashtable构造其实是一样的,不过其初始分配的大小是不一样的。

hash_map:
hash_map和map相比,底层是使用hashtable来实现的,所以hash_map不具有自动排序的功能。Java中,hash_map和hashtable相比,后者是线程安全的,而前者不是是。
除此之外,其他的使用方法是相同的,可以参考我的《STL读书笔记》里面对map的描述。
  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: