STL ④ —— 哈希

1. 散列表

  • 根据 key 计算 key 在表中的位置的数据结构;是 key 和其所在存储地址的映射关系,即 hash(key) % size = index
struct node{
	void *key;
	void *value;
	struct node *next;
};

在这里插入图片描述

2. hash函数

2.1 hash函数的特点

  • 计算速度快
  • 强随机分布性(等概率、均匀地分布在整个地址空间)
  • 现有的hash函数:
    • murmurhash1,murmurhash2,murmurhash3,其中1的速度最快但质量一般,3的质量最好但速度慢,2是两者均衡的也是使用最广泛的;
    • siphash,在redis6.0当中使用,rust 等大多数语言都选用该hash算法来实现hashmap,主要解决字符串接近的强随机分布性;
    • cityhash,与murmurhash是同一作者,也具备强随机分布性,是murmurhash的优化。

2.2 负载因子

  • 负载因子 = 数组存储元素的个数 / 数组长度;
  • 用来形容散列表的存储密度;负载因子越小,冲突概率越小,负载因子越大,冲突概率越大。

2.3 冲突处理

  • 冲突处理的方法有两种不同的情况:一种情况是负载因子在合理范围内,即key的数量小于哈希数组的数量,这时候可以使用链表法或开放寻址法;另一种情况是负载因子不在合理范围内的情况

2.3.1 若负载因子在合理范围内

链表法
  • 引用链表来处理哈希冲突;也就是将冲突元素用链表链接起来;
  • 可能出现一种极端情况,冲突元素比较多,该冲突链表过长,这个时候可以将这个链表转换为红黑树、最小堆;由原来链表时间复杂度 O(n) 转换为红黑树时间复杂度 O(log n);
    • 那么判断该链表过长的依据是多少?可以采用超过 256个节点的时候将链表结构转换为红黑树或堆结构(java hashmap);

开发寻址法

  • 将所有的元素都存放在哈希表的数组中,不使用额外的数据结构;一般使用线性探查的思路解决;
  • 步骤:
      1. 当插入新元素的时,使用哈希函数在哈希表中定位元素位置;
      1. 检查数组中该槽位索引是否存在元素。如果该槽位为空,则插入,否则进入步骤3;
      1. 在步骤2检测的槽位索引上加一定步长接着检查步骤2; 加一定步长分为以下几种:
      • i+1, i+2, i+3, i+4, … , i+n
      • i-1^2, i+2^2, i-3^2, i+4^2, …
      • 这两种都会导致同类hash聚集;也就是近似值它的hash值也近似,那么它的数组槽位也靠近,形成 hash 聚集;第一种同类聚集冲突在前,第二种只是将聚集冲突延后; 另外还可以使用双重哈希来解决上面出现hash聚集现象:

2.3.2 负载因子不在合理范围内:

  • 扩容:used > size 翻倍扩容
  • 缩容:used < 0.1 * size
  • rehash:由于size改变了,所以所有的key需要重新使用 hash(key) % size = index 得到新的索引值

3. STL散列表实现

  • unordered_set、unordered_map、unordered_multiset、unordered_multimap的底层实现都是使用hash
  • 为了实现迭代器的顺序访问,将后面具体节点串成一个单链表
    在这里插入图片描述

4. 布隆过滤器

  • 背景:

    • 布隆过滤器是一种概率型数据结构,它的特点是高效地插入和查询,能确定某个字符串一定不存在或者可能存在;
    • 布隆过滤器不存储具体数据,所以占用空间小,查询结果存在误差,但是误差可控,同时不支持删除操作。
  • 构成:

    • 位图(BIT 数组)+ n 个 hash 函数
    • m % 2^n = m & (2^n - 1)
      在这里插入图片描述
  • 原理:

    • 当一个元素加入位图时,通过 k 个 hash 函数将这个元素映射到位图的 k 个点,并把它们置为 1;当检索时,再通过 k 个 hash 函数运算检测位图的 k 个点是否都为 1;如果有不为 1 的点,那么认为该 key 不存在;如果全部为 1,则可能存在。
      在这里插入图片描述
  • 不支持删除操作:

    • 在位图中每个槽位只有两种状态(0 或者 1),一个槽位被设置为 1 状态,但不确定它被设置了多少次;也就是不知道被多少个 key 哈希映射而来以及是被具体哪个 hash 函数映射而来。
  • 根据n和p,算出m和k

    • n: 预期布隆过滤器中元素的个数,如上图只有str1和str2 两个元素,那么 n=2
    • p:假阳率,在0-1之间
    • m:位图所占空间
    • k:hash函数的个数

5. 分布式一致性hash

  • 背景:
    • 分布式一致性 hash 算法将哈希空间组织成一个虚拟的圆环,圆环的大小是 2^32;
    • hash(key) % bit_size = index
    • hash(ip) % 2^32,最终会得到一个 [0, 2^32 - 1] 之间的一个无符号整型,这个整数代表服务器的编号;多个服务器都通过这种方式在 hash 环上映射一个点来标识该服务器的位置;当用户操作某个 key,通过同样的算法生成一个值,沿环顺时针定位某个服务器,那么该 key 就在该服务器中。
      在这里插入图片描述
  • 解决了什么问题?
    • 解决了分布式缓存扩容的问题
  • 如何解决?
    • 当服务器节点增加时,用户所存的服务器节点就会改变,这样就会导致全局缓冲失效
    • 通过固定算法,即取余的值固定,为2^32,这样增加服务器节点时,全局缓存失效变成局部缓存失效,也就是增加节点的周围的用户缓存失效了
    • 再通过数据迁移的方法,将失效用户的缓存迁移到正确的服务器节点,就可以避免局部缓存失效
    • 通过加入虚拟节点,可以保证数据均衡
      在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/487374.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

由浅到深认识Java语言(21):Math类

该文章Github地址&#xff1a;https://github.com/AntonyCheng/java-notes 在此介绍一下作者开源的SpringBoot项目初始化模板&#xff08;Github仓库地址&#xff1a;https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址&#xff1a;https://blog.c…

Spring IoC DI(1)

IoC & DI入门 Spring 通过前面的学习, 我们知道了Spring是一个开源框架, 它让我们的开发更加简单. 它支持广泛的应用场景, 有着活跃且庞大的社区, 这就是Spring能够长久不衰的原因. 但是这个概念还是比较抽象. 可以用更具体的话描述Spring, 那就是: Spring是包含了众多…

HAL STM32G4内部运放的使用

HAL STM32G4内部运放的使用 &#x1f4cd;相关篇《HAL STM32G4 ADC手动触发采集各种滤波算法实现》&#x1f388;《HAL STM32G4 TIM1 3路PWM互补输出VOFA波形演示》 ✨继欧拉电子无刷电机驱动相关视频学习&#xff0c;STM32G4内部运放的使用。主要是为了采集无刷电机&#xff0…

《深入浅出LLM 》(二):大模型基础知识

&#x1f389;AI学习星球推荐&#xff1a; GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方向综述、论文等成体系的学习资料&#xff0c;配有全面而有深度的专栏内容&#xff0c;包括不限于 前沿论文解读、…

C语言栈和队列(个人笔记)

栈和队列 栈1.1栈的概念和结构1.2栈的实现 队列2.1队列的概念及结构2.2队列的实现2.3循环队列 栈和队列笔试题3.1[有效的括号](https://leetcode.cn/problems/valid-parentheses/submissions/516297357/)3.2[用队列实现栈](https://leetcode.cn/problems/implement-stack-using…

c盘清理软件绿色免安装版老电脑的福音

家里有一台老电脑笔记本&#xff0c;10年前的产品了&#xff0c;内存也不大&#xff0c;只有2G&#xff0c;安装360后&#xff0c;就卡的不行了&#xff0c;安装他的目的其实就是为了定期清理一下C盘空间&#xff0c;为了解决这个问题&#xff0c;于是做了一下研究&#xff0c;…

【Java常用API】正则表达式练习

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

安卓转鸿蒙竟如此丝滑

随着鸿蒙的爆火&#xff0c;大家都想知道鸿蒙能不能搞&#xff1f; 相信大家搞开发的&#xff0c;都多多少少的了解过鸿蒙。近几个月鸿蒙的大动作也不少&#xff0c;如&#xff1a;重庆市近20个垂域应用与鸿蒙原生合作、深圳制定鸿蒙《行动计划》、阿里再次与鸿蒙展开合作&…

文件操作3

随机读写数据文件 一、随机读写原理 在我们写数据时&#xff0c;有一个光标不断的在随着新写入的数据往后移动&#xff1b; 而读数据时&#xff0c;也有一个看不见光标&#xff0c;随着已经读完的数据&#xff0c;往后移动 这里的文件读写位置标记——可以想象成图形界面里的…

计算机程序的编译和链接

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

代码随想录第20天| 654.最大二叉树 617.合并二叉树

654.最大二叉树 654. 最大二叉树 - 力扣&#xff08;LeetCode&#xff09; 代码随想录 (programmercarl.com) 又是构造二叉树&#xff0c;又有很多坑&#xff01;| LeetCode&#xff1a;654.最大二叉树_哔哩哔哩_bilibili 给定一个不重复的整数数组 nums 。 最大二叉树 可以…

python+selenium做ui自动化测试用法必会

一、前言 大家都知道&#xff0c;基于Web端的测试的基础框架是需要Selenium做主要支撑的&#xff0c;这里边给大家介绍下Web测试核心之基于Python的Selenium Selenium是用于测试Web应用程序用户界面(UI)的常用框架。它是一款用于运行端到端功能测试的超强工具。您可以使用多个编…

ExperimentalWarning: The http2 module is an experimental API.

错误提示 Node.js:ExperimentalWarning: The fs.promises API is experimental原因是node的版本不是最新的&#xff0c;而在项目引入的模块是最新的&#xff0c;node.js的版本低于模块的版本&#xff1a; 解决方法: 1、升级版本 npm install -g npm 更新npm到最新版 npm ins…

MyBatis3源码深度解析(二十一)动态SQL实现原理(二)动态SQL解析过程、#{}和${}的区别

文章目录 前言8.5 动态SQL解析过程8.5.1 SQL配置转换为SqlSource对象8.5.2 SqlSource转换为静态SQL语句 8.6 #{}和${}的区别8.7 小结 前言 在【MyBatis3源码深度解析(二十)动态SQL实现原理(一)动态SQL的核心组件】中研究了MyBatis动态SQL相关的组件&#xff0c;如SqlSource用于…

vue.js制作学习计划表案例

通俗易懂&#xff0c;完成“学习计划表”用于对学习计划进行管理&#xff0c;包括对学习计划进行添加、删除、修改等操作。 一. 初始页面效果展示 二.添加学习计划页面效果展示 三.修改学习计划完成状态的页面效果展示 四.删除学习计划 当学习计划处于“已完成”状态时&…

Linux基础-Makefile

目录 一、Make简介 二、Makefile基本结构 示例&#xff1a; 补充(Makefile)&#xff1a; 伪目标&#xff1a; 三、创建和使用变量 变量定义的方式&#xff1a; 简单方式&#xff1a; 递归方式&#xff1a; 用?定义变量 为变量添加值 预定义变量 例 自动变量 例…

C++函数模板详解(结合代码)

目录 1. 模板概念 2. 函数模板语法 3. 函数模板注意事项 4. 函数模板案例 5. 普通函数与函数模板的区别 6. 普通函数与函数模板的调用规则 7. 模板的局限性 1. 模板概念 在C中&#xff0c;模板是一种通用的程序设计工具&#xff0c;它允许我们处理多种数据类型而不是固…

【STM32嵌入式系统设计与开发】——9Timer(定时器中断实验)

这里写目录标题 一、任务描述二、任务实施1、ActiveBeep工程文件夹创建2、函数编辑&#xff08;1&#xff09;主函数编辑&#xff08;2&#xff09;USART1初始化函数(usart1_init())&#xff08;3&#xff09;USART数据发送函数&#xff08; USART1_Send_Data&#xff08;&…

【Java基础知识总结 | 第六篇】Java反射知识总结

文章目录 6.Java反射知识总结6.1概述6.1.1什么是反射&#xff1f;6.1.2为什么使用反射&#xff1f; 6.2反射的原理6.3反射的使用6.3.1获取类对象&#xff08;1&#xff09;通过具体类的类名获取&#xff08;2&#xff09;通过对象实例获取&#xff08;3&#xff09;通过class.f…

正式发布:VitePress 1.0 现代化静态站点生成器!

大家好&#xff0c;我是奇兵&#xff0c;今天介绍一下现代化静态站点生成器!&#xff0c;希望能帮到大家。 3 月 21 日&#xff0c; 由 Vue 团队出品的现代化静态站点生成器 VitePress 正式发布 1.0 版本&#xff01;它专为构建快速、以内容为中心的网站而生&#xff0c;能够轻…