产生原因

在顺序结构或树形结构的数据集合中,我们想要查询一个元素时,必须进行遍历,所以顺序结构的查询时间复杂度为O(N),树形结构查询的时间复杂度为O(log2^N),但是我们想要一种不用遍历就知道其位置的方法,我们在查询时就会很方便。

哈希

哈希也叫作映射,我们可以通过其元素的值(关键码),查找到该元素的具体位置。我们将这种一一对应的称为映射。==哈希是一种存储结构。==通过这种映射方式构造出来的结构称为散列表。

举一个简单栗子:一次函数。

我们知道x值,通过函数表达式,我们就可以计算出y的值。这种一一对应的关系就是映射,这个函数表达式就是哈希函数。

  • 插入元素:根据插入的元素(关键码),通过哈希函数计算出存储位置,将元素插入到指定位置。
  • 查询元素:将该元素通过哈希函数计算出相应的位置,我们在将该位置的元素取出,判断值是否相等,如果相等则表示存在。


上述的方法确实能够实现查询的时间复杂度为O(1),但是也存在一个问题,如果我们插入的元素是2,22,32,222呢?我们通过哈希函数计算的位置相同,这就是哈希冲突。

哈希冲突

不同的元素通过哈希函数计算出来的位置相同,我们称其为哈希冲突或者哈希碰撞。
产生哈希冲突的原因之一:哈希函数设计缺陷:

  • 哈希函数设计的方法:
  1. 直接定值法:就类似于线性函数 y = kx+b的形式。
  2. 除留余数法:类似于上述栗子中的方法。
  3. 平方取中法:取一个数的平方中间几位数。
  4. 数学分析法:找一些数的规律,利用规律设计哈希函数。

哈希函数的设计是有效的预防哈希冲突,但是不能避免产生哈希冲突。如何避免哈希冲突:闭散列、开散列。

闭散列

开放定值法,当发生哈希冲突时,如果哈希表没有装满,说明在哈希表中必然还有空位置,那么我们可以将元素放到冲突的下一个位置。如何寻找下一个位置。

  • 线性探测:从发生冲突的位置开始,依次向后探测,直到找到下一个空位置为止。

    • 线性探测插入方法:通过哈希函数判断插入的位置。如果该位置没有元素则直接插入新元素,如果该位置发生哈希冲突,则使用线性探测找到写一个位置。
    • 线性探测删除方法:在线性探测不能随便删除一个元素,因为直接删除会影响到其他元素的搜索,所以删除采用的是伪删除。
    • 扩容时机
      负载因子=当有效元素的个数/闭散列的长度。当负载因子大于0.7时,需要进行扩容。
    • 缺点:
      容易产生线性堆积,导致查询效率降低。

为了解决线性探测所产生的线性堆积问题,我们避免产生数据堆积在一起,我们提出二次探测。

  • 二次探测:探测方式:Hi = (Ho + i^2)%capacity,i取值为1,2,3, ……

    • 扩容机制:
      当负载因子大于0.5,就需要考虑扩容。

闭散列就是用空间换时间的思想,提高查询效率

开散列

开散列称为链地址法,将通过哈希函数计算出具有相同地址空间的元素放在同一个子集中,这个子集我们称为哈希桶,桶中的元素通过单链表的链接起来。但是单链表插入分为头插与尾插,这里采用头插法进行讲解。

我们可以看出,每一个哈希桶中都存放的是产生哈希冲突的元素。

  • 扩容时机:当所有桶中元素的个数等于容量时,哈希表扩容。

开散列中增加链表指针,看似比闭散列中多了一个内存开销,但是由于闭散列中存在二次探测,二次探测的负载因子在达到0.5就需要进行扩容,总和来看,开散列更加节省空间

C++---哈希闭散列与开散列相关推荐

  1. 哈希---闭散列和开散列

    闭散列法和开散列法解决哈希冲突 闭散列: 也叫开放定址法,当发生哈希冲突时,寻找合适的空位置 找空位置的方法: 线性探测法 从发生冲突的位置开始,依次向后探测,直到寻找到下一个空位置为止 线性探测优点 ...

  2. C++:哈希(闭散列、开散列)

    文章目录 哈希概念 哈希冲突 哈希函数 哈希冲突解决 闭散列 什么时机增容,如何增容? 线性探测的实现 开散列 开散列增容 开散列的实现 开散列与闭散列比较 unordered_map模拟实现(应用开 ...

  3. 【C++】哈希(闭散列,开散列)

    哈希 unordered系列关联式容器 unordered_map&& unordered_set 关联性容器介绍 介绍 底层结构 哈希概念 哈希冲突 闭散列 闭散列介绍 实现 开散列 ...

  4. 【C++】哈希——unordered系列容器|哈希冲突|闭散列|开散列

    文章目录 一.unordered系列关联式容器 二.哈希概念 三.哈希冲突 四.哈希函数 五.解决哈希冲突 1.闭散列--开放定址法 2.代码实现 3.开散列--开链法 4.代码实现 六.结语 一.u ...

  5. 哈希 ---《哈希函数》------除数的选取为什么是质数?、《哈希冲突》------解决方法、《闭散列》、《开散列》

    一.哈希概念 顺序结构以及平衡树中,元素关键码与其存储位置之间没有对应的关系,因此在查找一个元素时,必须要经过关键码的多次比较**.顺序查找时间复杂度为O(N),平衡树中为树的高度,即O(logN ) ...

  6. 哈希(Hash) - 开散列/闭散列

    文章目录: 认识哈希 哈希函数 处理冲突的方法 闭散列(开放定址法) 开散列(链地址法) 哈希表闭散列实现 闭散列基本框架 哈希表闭散列插入(insert) 哈希表闭散列删除(erase) 哈希表闭散 ...

  7. 哈希之开散列,闭散列

    先从数据查找开始说起吧,在线性结构,树形结构当中查找一个元素必须经过多次和一些元素进行比较,然后通过比较,查找到对应元素,这种方法多多少少,时间复杂度都是比较高的. 有没有一种方法时间复杂度,仅仅O( ...

  8. 【c++】哈希---unordered容器+闭散列+开散列

    1.unordered系列关联式容器 在C++98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到 logN,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也 ...

  9. c++哈希(哈希表开散列实现)

    文章目录 0. 前言 1. 开散列 1.1 开散列概念 2. 开散列的代码实现 2.0 定义 2.1 插入实现--Insert 2.2 查找实现--Find 2.3 删除实现--Erase 2.4 仿 ...

最新文章

  1. 用模板来进行类型检查。
  2. Java JDK11快速下载地址
  3. 编程语言分类及python所属类型
  4. ajax headers 参数有什么用_动态爬虫(ajax)-爬取bilibili热门视频信息
  5. 怎么通过java去调用并执行shell脚本以及问题总结
  6. 使用函数处理数组 高阶函数 js
  7. Oracle基础(六) 数据类型
  8. 【Linux】Linux的常用远程工具
  9. 揪出造成失败用户登录的应用主机名、数据库用户信息
  10. 关于程序员面试时的智力题集锦
  11. 基础版专业版全屏海报图片轮播代码生成器(淘宝店铺特效装修工具软件)
  12. 数字电子技术第二章--逻辑代数与逻辑函数化简
  13. win7怎么安装mac虚拟机linux,mac虚拟机如何安装win7详细教程
  14. Android 自带工具生成图标
  15. ubuntu16.04 创建用户,赋予权限
  16. OWA动态密码短信认证方案,解决outlook邮件双因子认证问题
  17. Kindle 2 和 iPad,不是零和游戏
  18. 五千字长文为你揭秘滴滴共享出行派单算法原理(干货)
  19. 教你文件改名后怎么恢复回原来名字
  20. python 色卡,如何使用opencv创建实验室色卡?

热门文章

  1. 「镁客早报」传SpaceX计划展开7.5亿美元贷款融资;LG开始为苹果生产OLED面板
  2. 集群服务器下使用SpringBoot @Scheduled注解定时任务
  3. 【Sofa】Sofa比赛成绩记录
  4. wcf服务契约代理链
  5. 关于C#的数据绑定,存取数据库实例详解 (三)
  6. Essential Chart for ASP.NET MVC商业图表控件相关介绍及下载
  7. 陶哲轩实分析 命题7.2.5 证明
  8. The Double-Checked Locking is Broken Declaration
  9. 梅西精彩过人绝技,太帅了!
  10. 052、JVM实战总结:从测试到上线:如何分析JVM运行状况及合理优化?