STL ④ —— 哈希

news2024/12/26 10:51:40

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,这样增加服务器节点时,全局缓存失效变成局部缓存失效,也就是增加节点的周围的用户缓存失效了
    • 再通过数据迁移的方法,将失效用户的缓存迁移到正确的服务器节点,就可以避免局部缓存失效
    • 通过加入虚拟节点,可以保证数据均衡
      在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

013_Linux(上传rz,下载sz,tar,zip,unzip)

目录 一、上传、下载 1、通过鼠标操作 &#xff08;1&#xff09;下载 &#xff08;2&#xff09;上传 2、通过命令操作 rz、sz &#xff08;1&#xff09;下载 sz &#xff08;2&#xff09;上传 rz 二、压缩、解压 1、tar命令 &#xff08;1&#xff09;压缩 &…

成为创作者的第 730 天——创作纪念日

​​ 文章目录 &#x1f4e8; 官方致信&#x1f3af;我的第一篇文章&#x1f9e9; 机缘与成长 &#x1f3af; 成就&#x1f3af; 目标 &#x1f4e8; 官方致信 今天早上打开 CSDN 私信一看&#xff0c;看到了这一条消息&#xff0c;然后看了下日期。突然感慨到&#xff0c;是…

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

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

【Redis知识点总结】(六)——主从同步、哨兵模式、集群

Redis知识点总结&#xff08;六&#xff09;——主从同步、哨兵模式、集群 主从同步哨兵集群 主从同步 redis的主从同步&#xff0c;一般是一个主节点&#xff0c;加上多个从节点。只有主节点可以接收写命令&#xff0c;主节点接收到的写命令&#xff0c;会同步给从节点&#…

Maven从零到放弃:文档学习

学习背景&#xff1a; Maven一直在使用&#xff0c;自己也构建过相应的项目。也对常用的配置和命令有一些了解&#xff0c;也处理过一些相关的问题。例如&#xff1a;项目缺少依赖&#xff1b;版本冲突或其他构建失败的问题。但是一直没有进行系统性的学习。 链接&#xff1a;…

Redis锁,乐观锁与悲观锁

锁 悲观锁 认为什么时候都会出问题&#xff0c;无论做什么都会加锁 乐观锁 很乐观&#xff0c;认为什么时候都不会出问题&#xff0c;所以不会上锁。 更新数据时去判断一下&#xff0c;在此期间&#xff0c;是否有人修改过这个数据 应用于&#xff1a;秒杀场景 **watch*…

小白如何兼职赚得第一桶金?六大网络赚钱方式助你轻松开启副业之旅

小白如何兼职赚得第一桶金&#xff1f;六大网络赚钱方式助你轻松开启副业之旅 无需担忧&#xff0c;以下为你精心挑选的六大线上兼职方式&#xff0c;将助你轻松开启副业赚钱之旅。 1&#xff0c;参与网络调查&#xff1a;市场调研公司及品牌商为洞察消费者需求&#xff0c;常…

第14篇:2线-4线译码器

Q&#xff1a;有编码器那对应的就会有译码器&#xff0c;本期我们来设计实现2线-4线二进制译码器 。 A&#xff1a;基本原理&#xff1a;译码器是编码器的逆过程&#xff0c;其功能是将具有特定含义的二进制码转换为对应的输出信号。2线-4线二进制译码器有2个输入共4种不同的组…

九州金榜|孩子产生厌学心理应该怎么办?

孩子厌学孩子在成长学习过程中的一个经历&#xff0c;也是家长在对孩子教育中遇到的一大挑战&#xff0c;孩子产生厌心理家长要怎么办呢&#xff1f;很多家长会对此很无奈&#xff0c;下面九州金榜家庭教育给几个方法&#xff0c;帮助家长疏导孩子厌学心理。 来百度APP畅享高清…

图像变换(python)

前言 这个Python没学过&#xff0c;写的是真的不方便&#xff0c;有很多问题还没解决&#xff0c;暂时不想写了&#xff0c;感兴趣的同学可以完善一下。设计的思路就是摆几个控件然后将对应的函数实现&#xff0c;这个Python的坐标放置以及控件的大小我没弄懂&#xff0c;算出…

shell实现查询进程号并批量kill(脚本)

问题或需求描述 在shell中&#xff0c;如果你想通过命令行查询出一系列匹配某个关键词的进程&#xff0c;并使用xargs命令批量结束这些进程&#xff0c;可以按照以下步骤操作&#xff1a; # 查询并提取进程号 pgrep -f "关键词" | xargs kill# 或者&#xff0c;如果…

Linux Load AVG linux 平均负载是什么? 简单解释说明

linux 命令基础汇总 命令&基础描述地址linux curl命令行直接发送 http 请求Linux curl 类似 postman 直接发送 get/post 请求linux ln创建链接&#xff08;link&#xff09;的命令创建链接&#xff08;link&#xff09;的命令linux linklinux 软链接介绍linux 软链接介绍l…

CI/CD实战-jenkins部署 3

安装 软件下载地址&#xff1a;Index of /jenkins/redhat/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 启动服务 安装推荐插件 不新建用户&#xff0c;使用admin账号登录 修改一下初始密码 新建项目测试 安装git命令 生成密钥 在gitlab中上传公钥 修改ssh 创建中…

22.保护性暂停扩展(一对一)

如果需要多个类之间使用GuardedObject对象&#xff0c;作为参数传递不是很方便&#xff0c;因此设计一个解耦的中间类&#xff0c;这样不仅能够解耦结果的等待者和结果生产者&#xff0c;还能够支持多个任务的管理。 Futures就好比居民楼一层的信箱&#xff0c;每个信箱有房间的…

清华大学突破性研究:GVGEN技术,7秒内从文字到3D高保真生成

引言&#xff1a;3D模型生成的挑战与机遇 随着计算机图形学的发展&#xff0c;3D模型的生成在各个行业中变得越来越重要&#xff0c;包括视频游戏设计、电影制作以及AR/VR技术等。在3D建模的不同方面中&#xff0c;从文本描述生成3D模型成为一个特别有趣的研究领域&#xff0c;…

哪些行业需要在线制作电子证书系统?

哪些行业需要在线制作电子证书系统&#xff1f; 1、教育机构&#xff1a;学校和培训机构需要为学生和培训者颁发证书&#xff0c;您的系统可以帮助他们快速生成和管理这些证书。 2、企业及政府部门&#xff1a;用于员工培训、资质认证等&#xff0c;提高内部管理效率。 3、专…

Learn OpenGL 29 延迟着色法

延迟着色法 我们现在一直使用的光照方式叫做正向渲染(Forward Rendering)或者正向着色法(Forward Shading)&#xff0c;它是我们渲染物体的一种非常直接的方式&#xff0c;在场景中我们根据所有光源照亮一个物体&#xff0c;之后再渲染下一个物体&#xff0c;以此类推。它非常…

2024 ccfcsp认证打卡 2023 09 01 坐标变换(其一)

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner in new Scanner(System.in);int n in.nextInt(); // 操作次数int m in.nextInt(); // 初始坐标个数int temp_x 0; // 临时存储x的累加值int temp_y 0; // 临时存储y的累…

星云小窝项目1.0——项目启动(二)

星云小窝项目1.0——项目启动&#xff08;二&#xff09; 文章目录 前言1. 从Github从下载它2. 使用编辑器打开&#xff08;以pycharm为例&#xff09;2.1. 下载所需要的模块2.2. 配置mysql数据库2.3. 配置QQ邮箱发送验证码2.4. 修改代码3. 启动总结 前言 上一篇博客大致介绍了…

用户态和内核态:操作系统权限与运行模式解析

在现代计算机操作系统中&#xff0c;用户态&#xff08;User Mode&#xff09;和内核态&#xff08;Kernel Mode&#xff09;是两种重要的运行模式&#xff0c;用于区分用户程序与操作系统核心之间的权限和特权级别。深入理解这两种模式对于理解操作系统的工作原理至关重要。 …