C++STL-无序容器-哈希表(散列存储)

本文介绍了C++STL中的无序容器-哈希表,强调了其查找效率高的特性。通过哈希函数,如直接定址法和除留余数法实现关键字到存储位置的映射,但也存在哈希碰撞问题。文章讨论了解决碰撞的线性探测、二次探测和链地址法(红黑树作为哈希桶)。此外,详细阐述了哈希表的创建、插入、查找和删除操作,以及闭散列和开散列的实现及其优缺点,特别提到了负载因子在两者中的应用和区别。
摘要由CSDN通过智能技术生成

有关于STL中的哈希表一些基础知识

  1. 为什么要设计哈希表——查找元素效率高 O(1),和关联式容器相比,无序容器擅长通过指定键查找对应的值;但对于使用迭代器遍历容器中存储的元素,无序容器的执行效率则不如关联式容器。
  2. 通过什么机制实现的——关键字通过哈希函数O(1)可以直接确定哈希地址,常见的有直接定址法、除留余数法
  3. 会产生什么问题——不同的关键字可能会得到相同的哈希地址,称为哈希碰撞
  4. 如何解决哈希碰撞——闭散列找空位置(每次向后找1或i^2),或者开散列在同一个哈希地址的键值对存在同一个哈希桶中,哈希桶可以是单链表或红黑树,哈希地址中存放单链表头结点或红黑树根节点存放在
  5. 闭散列和开散列比较——开散列更加实用,一是开散列的负载因子更大(闭散列负载因子不能超过 1,一般建议控制在 0.0 ~ 0.7 之间;开散列负载因子可以超过 1,一般建议控制在 0.0 ~ 1.0 之间),二是开散列在极端情况(所有关键字都得到同一个哈希地址,哈希表退化为单链表O(n))还可以采取红黑树O(log n) 作为哈希桶

四种数据存储结构:

  • 顺序存储:逻辑上相邻的数据元素其对应的物理存储位置也是相邻的)
  • 链式存储:每个元素一部分存储元素值本身,另一部分用于存放指向下一个元素的指针
  • 索引存储:索引表中的每一项包括关键字和地址,关键字是能够唯一标示一个数据元素的数据项,地址是指示数据元素的存储地址或者存储区域的首地址的
  • 散列存储:将数据元素存储在一个连续的区域,每一个数据元素的具体存储位置是根据该数据的关键字值,通过散列(哈希)函数直接计算出来的
四种无序容器 存储元素 key能否重复 key能否修改
unordered_map <key,value> NO NO
unordered_multimap <key,value> YES NO
unordered_set <value,value> NO NO
unordered_multise <value,value> YES NO

哈希表是牺牲空间换取时间,通过使用额外的数组、set或是map来存放数据,才能实现快速的查找。

哈希函数

要寻找哈希表中的元素,只需要通过哈希函数对该元素关键字进行计算,就可以得出存储地址,也就是说元素的存储位置与它的关键码之间能够建立一种映射的关系

直接定址法

关键字的某个线性函数作为哈希地址
H a s h ( k e y ) = a × k e y + b Hash(key)=a×key+b Hash(key)=a×key+b

除留余数法

散列表的长度是 m , p m,p mp0~m中最大的质数
H a s h ( k e y ) = k e y ( m o d ) p Hash(key)=key (mod) p Hash(key)=key(mod)p

哈希碰撞

不同关键字通过相同哈希函数计算出相同的哈希地址,该种现象称为 哈希冲突哈希碰撞,把具有不同关键码而具有相同哈希地址的数据元素称为 同义词。

线性探测

从发生冲突的位置依次向后查找,直到找到一个空位置

二次探测

从发生冲突的位置向后查找,每次往后移动 i^2 个位置,直到找到空位置,也就是每次往后移动的距离都会增大,不容易导致数据堆积

链地址法

首先对关键字集合通过哈希函数计算出哈希地址,将有相同哈希地址的关键字放在同一个子集合,也就是一个哈希桶,在哈希桶内部关键字通过单链表连接,头结点放在哈希表中
在这里插入图片描述

红黑树作为哈希桶(地址全都相同的情况)

所有元素全部产生冲突,最终都放到了同一个单链表中,此时该哈希表增删查改的效率就退化成 O ( N ) ,我们就可以用红黑树来作为哈希桶的数据结构。红黑树搜索时间复杂度是 O(logN)
在这里插入图片描述
但有些地方也会选择不把桶中的单链表结构换成红黑树结构,因为随着哈希表中数据的增多,该哈希表的负载因子也会逐渐增大,最终会触发哈希表的增容条件,此时该哈希表当中的数据会全部重新插入到另一个空间更大的哈希表,此时同一个桶当中冲突的数据个数也会减少,因此不做处理问题也不大。

具体函数操作

参考:C++ STL unordered_map容器用法详解

容器模板

template < class Key,                        //键值对中键的类型
           class T,                          //键值对中值的类型
           class Hash = hash<Key>,           //容器内部存储键值对所用的哈希函数
           class Pred = equal_to<Key>,       //判断各个键值对键相同的规则
           class Alloc = allocator< pair<const Key,T> >  // 指定分配器对象的类型

template < class Key,      //键(key)的类型
           class T,        //值(value)的类型
           class Hash = hash<Key>,  //底层存储键值对时采用的哈希函数
           class Pred = equal_to<Key>,  //判断各个键值对的键相等的规则
           class Alloc = allocator< pair<const Key,T> > // 指定分配器对象的类型
           > class unordered_multimap;

template < class Key,            //容器中存储元素的类型
           class Hash = hash<Key>,    //确定元素存储位置所用的哈希函数
           class Pred = equal_to<Key>,   //判断各个元素是否相等所用的函数
           class Alloc = allocator<Key>   //指定分配器对象的类型
           > class unordered_set;

template < class Key,            //容器中存储元素的类型
           class Hash = hash<Key>,    //确定元素存储位置所用的哈希函数
           class Pred = equal_to<Key>,   //判断各个元素是否相等所用的函数
           class Alloc = allocator<Key>   //指定分配器对象的类型
           > class unordered_multiset;

创建容器

  1. 调用模板类的默认构造函数,创建空的容器
std::unordered_map<std::string, std::string> umap;
  1. 创建的同时初始化
std::unordered_map<std::string, std::string> umap{
   
    {
   "Python教程","http://c.biancheng.net/python/"},
    {
   "Java教程"
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STL中使用哈希表容器有unordered系列关联式容器。这些容器采用了哈希的思想,存储和查找数据的效率非常高,能够达到理想的O(1)。\[2\] unordered系列关联式容器包括unordered_set、unordered_multiset、unordered_map和unordered_multimap。这些容器使用哈希函数将元素映射到桶中,以实现快速的插入、查找和删除操作。\[2\] 此外,还可以使用布隆过滤器来支持删除操作,通过将布隆过滤器中的每个比特位扩展成一个计数器,对应的哈希函数计算出的哈希值对应的计数器进行加减操作,以实现删除操作。\[3\] #### 引用[.reference_title] - *1* [【数据结构】—— 哈希表/STL使用技巧](https://blog.csdn.net/forever_bryant/article/details/126068847)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [<stl系列>哈希表详解,掌握stl容器从现在开始](https://blog.csdn.net/weixin_59371851/article/details/126917526)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值