C++八股文分享—数据结构其二—哈希表

前言

什么是哈希表?

搜索二叉树对值的查找是通过从根节点开始,逐个节点与目标值做比较,向下查找,直至找到目标值或是到达根节点未查找到,时间复杂度为O(logn)。而哈希表,则是通过将value与key成对绑定,将key带入哈希函数,即可得到目标值的存放地址,从而得到目标值,在不考虑哈希冲突的情况下,时间复杂度为O(1)。
哈希表其实可以理解为一个特殊的数组。我们通常使用的数组,通过下标0开始,直至数组长度len-1,依次存储数组元素,他们的地址是连续的。而哈希表是使用一段比原数据大一些的数组,通过哈希函数将key映射到数组中的某个地址上,存放是不连续的。

例如我们现在有int nums[20]一个整数数组,访问nums[3]的步骤为:
1、取到nums数组的首地址
2、根据首地址偏移sizeof(int)*3个字节,即可到达nums[3]的存储位置,得到其中元素

例如我们现在有一个哈希表hashmap(string, int) myhash,存储的是某人的身高。
myhash["张三"] = 175,myhash["李四"] = 180, 代表张三身高175cm,李四身高180。
现在获取张三身高myhash["张三"]的步骤为:
1、index = H("张三"),通过哈希函数H,得到哈希表内部对应数组的地址index
2、使用访问index指向的内存区域,得到张三的身高175

哈希函数的构造方法:

1、数字分析法 2、平方取中法 3、折叠法 4、除留余数法 。主要使用方法4。

哈希函数的注意事项:
1.计算散列地址所需要的时间(即hash函数本身不要太复杂)
2.关键字的长度,key过长就要考虑使用折叠法和除留余数法
3.哈希表的长度
4.关键字分布是否均匀,是否有规律可循
5.设计的hash函数在满足以上条件的情况下尽量减少冲突

关于构造方法的详解可参考:数据结构 Hash表(哈希表)
链接转自:CSDN-洌冰


哈希冲突的解决方法:

无论使用上面4种方法的哪一种来构造哈希函数,都会存在不同的key经过哈希函数计算出的地址相同的问题,这种情况就叫做哈希冲突。 对于动态查找表来说,由于数据的不断插入,哈希冲突的出现概率会更高。
解决哈希冲突有以下几种常用方法:
1.线性探测法:对于冲突的key,加上一个常量再检察是否冲突;若冲突则再加上该常量。如此循环。
1.二次探测:对于冲突的key,不是加上一个常量,而是加上c^2,由于平方操作时间复杂度较高,经公式推导,可不断使用Hi​=(H(key)+di​)MODmm进行递归计算,直至不冲突。
2.链地址法:对于冲突的key,经过哈希函数计算后得到了相同的索引,那么直接在该索引构建链表,将冲突的数据全部链在该链表中。
3.公共溢出区法:建立一个特殊存储空间,专门存放冲突的数据。此种方法适用于数据和冲突较少的情况。
4.再散列法:准备若干个hash函数,如果使用第一个hash函数发生了冲突,就使用第二个hash函数,第二个也冲突,使用第三个……

重点了解一下1、开放定制法和2、链地址法


哈希表元素的插入和rehash

插入:
首先我们要知道一个概念,负载因子负载因子 loadFactor=n/m,实际数据的长度除表长。

1、当loadFactor<=1时,hash表查找的期望复杂度为O(1).。因此,每次往哈希表中添加元素时,我们必须保证是在loadFactor<1的情况下,
才能够添加。
2、负载因子越大,平均查找长度越大,那么装载因子α越小越好?也不是,就像100的表长只存一个数据,查找时间很快,但空间浪费极大。通常
情况下,认为α=0.75是时间空间综合利用效率最高的情况。

rehash:
rehash,就是指当哈希表插入元素后其负载因子大于0.75时,需要对哈希表的空间和哈希函数进行调整的过程。
以C++中的hashmap为例,当负载因子大于等于0.75时,就需要进行rehash。rehash过程中,首先会开辟一个原来桶数组的两倍空间,称为新桶数组,然后把原来的桶数组中元素全部重新哈希到新的桶数组中。这个过程需要注意,因为新数组的大小变了,所以需要构造新的哈希函数,然后再将以前的key和value重新哈希到新数组中。


哈希表元素的删除:

当删除哈希表的一个元素时,如果处理哈希冲突使用的是链地址法可以直接删除。如果是开放定制法式肯定不行的,因为之前可能存在哈希冲突的情况,如果删除的是冲突1的元素,那么1后面冲突的元素就再也查找不到了,所以不能直接删除该元素。


扩展问题:

问:哈希表的桶个数,为什么是质数?

首先一定要明确一个概念,哈希表的桶个数,就是指使用除留余数法构造的哈希函数H(key)=key%p中的p值。 不是哈希表数据的长度,也不是哈希表的表长,这个概念很多文章写的模模糊糊,一定要搞清楚。
关于除留余数法请参考:数据结构 Hash表(哈希表)
链接转自:CSDN-洌冰

答:使用除留余数法构造哈希函数的哈希表在处理键值key时,就是使用键值除一个数字,得到的余数就是存储地址。如果p取合数,将会使得到的地址冲突概率更高,影响哈希表的效率;使用质数则可以减少冲突概率,使哈希表分部均匀,查找效率更高。

持续更新中…

C++八股文分享---数据结构其二---哈希表相关推荐

  1. 用c语言实现基本数据结构(哈希表)

    用c语言实现基本数据结构(哈希表) 写这个哈希表总是段错误,找了半天的bug...原来是各种小错误不断,写得很蛋疼. 我是是用数组实现的,数组的最大值定义成的宏.一共只有四个函数,分别为初始化哈希表, ...

  2. 图书馆管理系统(C、数据结构、哈希表、文件IO)

    目录 技术路线 实现效果展示 ​程序主体 1.头文件部分 2.自定义函数定义部分 3.main函数部分 注意 技术路线 数据结构.哈希表.文件IO 通过C语言进行程序设计,有用到数据结构中的哈希表,通 ...

  3. 【数据结构】哈希表的概念及应用

    [数据结构]哈希表的概念及应用 前言 1.写出哈希表的基本概念 2.列出常用的哈希函数构造方法,并阐述各自的特点. 直接定址法 除留余数法 数字分析法 其他构造整数关键字的哈希函数的方法: 平方取中法 ...

  4. 「Redis数据结构」哈希表(Dict)

    「Redis数据结构」哈希表(Dict) 文章目录 「Redis数据结构」哈希表(Dict) @[toc] 一.概述 二.结构 三.哈希冲突 四.链式哈希 五.rehash 六. 渐进式 rehash ...

  5. j - 数据结构实验:哈希表_一看就懂的数据结构基础「哈希表」

    哈希表 哈希表(Hash table),是存储键值(Key Value)对数据的一种数据结构. 例如,我们可以将人的名字作为键,性别作为值来存储.通过把键映射到表中的一个位置来访问数据,以提高查找速度 ...

  6. 数据结构:哈希表函数构造和冲突解决方法

    哈希表 哈希函数:记录的存储位置和它的关键字之间建立一个确定的对应关系. 冲突:对不同的关键字可能得到同一哈希地址,这种现象称为冲突. 哈希函数构造方法 1.直接定址法 取关键字或关键字的某个线性函数 ...

  7. 数据结构例程——哈希表及其运算的实现

    本文是[数据结构基础系列(8):查找]中第11课时[哈希表--散列结构]和第12课时[哈希表的运算]的例程. #include <stdio.h> #define MaxSize 100 ...

  8. Python数据结构:哈希表

    哈希 散列(哈希)是电脑科学中一种对资料的处理方法,通过某种特定的函数/算法(称为散列函数/算法)将要检索的项与用来检索的索引(称为散列,或者散列值)关联起来,生成一种便于搜索的数据结构(称为散列表) ...

  9. 【数据结构之哈希表(二)】 哈希表的扩容实现机制

    哈希表的扩容实现机制 导语 哈希表 什么是哈希表 装载因子 Hashcode 哈希冲突 扩容方案 Java中的实现 Redis中的实现 结束语 导语 哈希表是实际开发中非常常用的数据结构,也很重要.了 ...

最新文章

  1. java类的修饰词有哪些_Java类与对象及访问控制修饰词解析
  2. MySQL的主从复制延迟问题
  3. 猎鹰与龙飞船基于Linux,采用C++、Chromium与JS开发
  4. 组件化与插件化的差别在哪里?附面试题答案
  5. 深入浅出通信原理连载145-389(Python代码版)
  6. 操作系统PV操作题整理2
  7. cam350菜单怎么切换成中文_电子设计软件CAM350各菜单使用说明(一)
  8. 写给初学者,一文搞懂大数据学习、岗位、面试及简历
  9. C语言 定时器的原理,单片机定时器作用原理及学习应用详解
  10. 同一工作组计算机无法查看,win7系统在同一个工作组看不到其他电脑怎么回事?...
  11. ResponseEntity下载
  12. 计算机蓝屏代码0xc0000020,Win10打开软件提示“损坏的映像 错误0xc0000020”的解决方法...
  13. 数据结构 | 有关树和二叉树的详解【内附考点精析】
  14. 什么事LLVM和Clang?Clang与GCC有什么区别?Clang如何使用?
  15. 作为通信的学子,怎么在深度学习领域里面发论文
  16. 面向对象(4)封装与继承
  17. 梦想CAD控件com接口界面控制右键弹出菜单
  18. 自定义View,和Canvas(画布),Paint(画笔),Path(路径)的用法
  19. html5 li表格纵向合并,vue elementui 表格合并/纵向表头
  20. 新媒体管家plus(新媒体管家插件) v6.66官方最新版

热门文章

  1. Android 监听手机旋转角度
  2. Android第一行代码——第三章:控件的使用方法5A-00-1A-C4-8C-55(2009+jjy)
  3. 我可爱的卧龙凤雏同事又双叒叕搞了个BUG
  4. C语言中变量的作用域和生命周期
  5. spug上线服务踩坑记
  6. sql语句之存储过程,触发器,函数,事务,游标
  7. 面试时遇到『看门狗』脖子上挂着『时间轮』,我就问你怕不怕?
  8. 兼容IE的excel下载
  9. 统计结合python_python 练习(一)代码统计工具的实现
  10. MySQL中LAG()函数和LEAD()函数的使用