【C++】STL


什么是STL?

  • C++ STL从广义来讲包括了三类:容器、算法、迭代器。
  • 算法:包括遍历、查找、排序等常用算法,以及不同容器特定的算法。
  • 容器:就是数据的存放形式,包括序列式容器和关联式容器,序列式容器就是list,vector等,关联式容器就是set,map等。
  • 迭代器:就是在不暴露容器内部结构的情况下对容器的遍历。

迭代器:++ it、it ++哪个好,为什么

  • 前置返回一个引用,后置返回一个对象
  • 前置不会产生临时对象,后置必须产生临时对象,临时对象会导致效率降低
// ++i实现代码为:(前置)
int& operator++() {
  *this += 1;
  return *this;
} 

//i++实现代码为: (后置)              
int operator++(int) {
    int temp = *this;                   
   ++*this;                       
   return temp;                  
}

STL中hash_table的实现?

  • hash_set、hash_map、hash_multiset、hash_multimap四个关联容器都是以hashtable为底层实现方法(技巧)
  • Hashtable底层实现是通过开链法(开链法解决哈希冲突)来实现的,hash table表格内的元素称为桶(bucket),而由桶所链接的元素称为节点(node),其中存入桶元素的容器为stl本身很重要的一种序列式容器——vector容器。之所以选择vector为存放桶元素的基础容器,主要是因为vector容器本身具有动态扩容能力,无需人工干预。

1 原理

图片名称

  它通过把关键码(key)值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。给定表M,存在散列函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,映射函数f(key)为哈希函数(散列函数)。

哈希表的底层实际上是基于数组来存储的

  • 当插入键值对时,并不是直接插入该数组中,而是通过对键进行Hash运算得到Hash值,然后和数组容量取模,得到在数组中的位置后再插入。
  • 取值时,先对指定的键(key)求Hash值,再和容量取模得到底层数组中对应的位置,如果指定的键值与存储的键(key)相匹配,则返回该键值对,如果不匹配,则表示哈希表中没有对应的键值对。

这样做的好处是在查找、插入、删除等操作可以做到O(1),最坏的情况是O(n),当然这种是最极端的情况,极少遇到。

实现哈希表我们可以采用两种方法:

  • 1、数组+链表
  • 2、数组+二叉树

2 哈希冲突

  对不同的关键字可能得到同一散列地址,即k1≠k2,而f(k1)=f(k2),这种现象称为哈希冲突

  很明显,极端情况下如果数组容量为1,哪必然发生碰撞,如果数组容量无限大,哪碰撞的概率非常之低。所以,哈希碰撞还取决于负载因子。负载因子是存储的键值对数目与数组容量的比值,比如数组容量100,当前存贮了90个键值对,负载因子为0.9。负载因子决定了哈希表什么时候扩容,如果负载因子的值太大,说明存储的键值对接近容量,增加碰撞的风险,如果值太小,则浪费空间

主要有四类处理冲突的方法:

  • 开链法(常用)
  • 开放定址法(常用)
  • 公共溢出区(不常用)
  • 再Hash法(不常用)

2.1 开链法

  主要思想是基于数组和链表的组合来解决冲突,桶(Bucket)中不直接存储键值对,每个Bucket都链接一个链表,当发生冲突时,将冲突的键值对插入链表中。

  • 优点在于方法简单,非同义词之间也不会产生聚集现象(相比于开放定址法),并且其空间结构是动态申请的,所以比较适合无法确定表长的情况
  • 缺点是链表指针需要额外的空间,遇到碰撞拒绝服务时会退化为单链表。

2.2 开放定址法

  主要思想是发生冲突时,直接去寻找下一个空的地址,只要底层的表足够大,就总能找到空的地址。这个寻找下一个地址的行为,叫做探测

2.3 公共溢出区

主要思想是建立一个独立的公共区,把冲突的键值对都放在其中。不常用,这里不再细述。

2.4 再Hash法

主要思想是有冲突时,换另外一个Hash函数来算Hash值。不常用,这里不再细述。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇光_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值