stl之关联容器——set,map,hashtable

关联容器

        每笔数据都是一个键值对(key-value-pair)。当元素被插入到关联式容器中时,容器内部结构便依照其键值大小,以某种特定规则将这个元素放置于适当位置。关联容器没有所谓的头尾,所以不会有所谓的push_back()、push_front()、pop_back()、pop_front()这种操作行为。

set 与multiset

其底层实现结构为RB-tree。

常用方法如下:

insert //返回pair<iterator,bool>类型,第一个元素是个RB_tree迭代器,指向新增节点,第二元素表示插入是否成功,本质上调用了保持RB_tree(旋转及改变颜色)的方法:__rb_tree_rebalance

begin

end

find   //一般应使用这个,其查找速度为lgn,要好于算法库的find函数

swap

key_compare //键值比较函数,默认使用less<T>

value_compare //对于set来说和key_compare一样

erase //参数可以是迭代器,键值,迭代器区间

upper_bound //返回指向最大值的迭代器

lower_bound //返回指向最小值的迭代器

equal_range   //return pair<iterator,iterator>(lower_bound(__k), upper_bound(__k));

multise是t允许重复的键值的set(set调用的是RB-tree的insert_unique,而map调用的是insert_equal)。

map与multimap

于set的实现类似,使用也类似。其在set方法的基础上增加了 [],[]返回的结果既可作为左值,也可作为右值。multimap允许重复的键值。可以把set当成键和值一样的map。

hashtable

         stl采用拉链法解决冲突其由vector和list结构构成。其中vector内的元素称为bucket,bucket下链接了bucketlist。这边bucket所维护的linked list并不采用STL的list或slist,而是自行维护的hash table node。vector充当着buckets的聚合体,以便使hashtable具有动态扩充的能力。其示意图如下(摘自侯捷的”stl源码剖析”):


         stl中的hashtable重建条件:当元素个数size(把新增元素计入后)>bucketvector的大小时,则重建hashtable,即采用更大的vector(hashtable内维护了一个升序的质数数组(起始元素为53),vector的大小将扩充为接近且较大的质数)。然后对hashtable中的元素进行重映射。

stl中的hashtable只为char intlong short 和char *类型定义了hash函数,其中char *的转换函数如下(位于stl_hash_fun.h文件中):

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

而其余类型只是简单地返回真实值:如int类型的hash函数为

__STL_TEMPLATE_NULL struct hash<int>{
 size_t operator()(int __x) const { return __x; }
};

而计算元素在hashtable中的位置是通过调用:

 size_type _M_bkt_num_key(const key_type& __key, size_t __n) const
  {
   return _M_hash(__key) % __n;
  }

其中 _M_hash 即所指定的hash函数。

tips:

         SGIhashtable无法处理上述所列各项型别以外的元素,例如string,double, float。欲处理这些型别,用户必须自行定义相应的hash function,对const char *类型,不能沿用缺省的equal_to<T>,因为const char *没有提供operator == 运算符,必须通过使用strcmp函数来比较大小。

hash_set与hash_map

hash_set与hash_map是以hashtable为底层容器实现的,而set和map是以RB-tree实现的,容器的差异决定了set和map的元素具有自动排序功能而hash_set没有。

hash_set的使用方式,与set完全相同,实际使用中看是否需要排序功能,需要的话就不能选择hash_set和hash_map,而需选择set和map

如果使用时没指定空间大小时,其初始大小缺省为100,这可以从stl_hash_map.h和stl_hash_set.h中了解到。

使用方式:

hash_set:

hash_set:其key和value是同一种类型,所以模版类型只需三个参数

hash_set<int, hash<int>,equal_to<int>>

其中第二个和第三个参数可缺省,即使用缺省的hash<T> 和equal_to<T>.

hash_map:

模版:hash_map<key_type, value_type, hashFcn, EqualKey>:

实例:hash_map<int, int, hash<int>, equal_to<int>>


同set和map,hash_set及hash_map提供了与其对应的find函数,其效率高于algorithm中的find

此外,对应键值可重复的情况,stl提供了hash_multiset和hash_multimap


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值