【哈希】哈希表|除留取余法|哈希冲突(拉链法interv)|一致性哈希|虚拟节点

news2024/12/27 11:27:10

哈希 = hash = 散列函数(将非常大范围的输入,通过一定的函数,可以转换到小规模的输出)

什么是哈希?

广义上是一种思想,不是一个特定的东西,只要算法设计中使用到了哈希思想,就可以叫做哈希函数。

  1. 存储地址 = f(关键字)
  2. 可以直接通过关键字而不是去一次比较,直接获取存储地址。
  3. 散列技术,其实是将存储位置和关键字之间确立了一种对应关系f,使得每一个关键字(key)都对应一个存储位置。
    查找的时候通过确定的对应关系,找key值的映射f(key)。
    这种对应关系f就是散列函数(哈希函数),采用散列技术将记录存在一片连续的存储空间,这个空间就被称为哈希表
    通俗的讲:就是一片连续的存储空间存储了 通过散列函数计算的散列地址,并记录了其映射关系
    散列技术,既是一种存储方法,也是一种查找方法。
    例如:单链表和顺序表,数据和数据之间有没有关系?
    单链表各个结点之间:上一个结点存储了下一个结点的地址
    顺序表之间:逻辑上相邻,物理上也相邻
    哈希表:数据与数据之间没有关系,但是数据本身和最终存储空间有唯一的关系。
    存储地址 = f(关键字)

散列函数怎么设计(6种方法)(面试不会考)

                        直接定址法(线性关系) f(key) = key

使用最多的是:除留取余法
可以穿插使用

哈希冲突怎么解决?(4种方法)(不可避免,尽可能的减少哈希冲突)

公司:以空间换时间。
1.开放定址法
(线性探测):只向后探测 (造成的问题:导致前方有空间大量闲余,后方空间紧张,并且会出现数据堆积)
(平方探测):向前向后探测
.向后探测是否有空心的值
2.拉链法
3.公共溢出法(基本表和溢出表)
请添加图片描述

其中链式哈希必须 会写

 #define HASHSIZE 12
typedef int ELEMTYPE;
typedef struct LNode
{
	ELEMTYPE data;
	LNode* next;
}LNode,*PLNode;
typedef struct Head
{
	struct LNode arr[HASHSIZE]; //指针数组(存放指针的数组)
}Head,*PHead;   //直接设计为LNode类型,可以直接访问LNode中的数据

请添加图片描述

 #include "listhash.h"



void Init_listhash(PHead ph)
{
	//assert ;
	for (int i = 0; i < HASHSIZE; i++)
	{
		//ph->rr[i].data 不使用
		ph->arr[i].next = nullptr;
	 }
}
bool Insert_hash(PHead ph, int key)
{
	int hash = key % HASHSIZE;
	//创建新结点
	struct LNode* s = (LNode*)malloc(sizeof(LNode)*1);
	assert(s != nullptr);
	//插入;
	s->data = key;
	s->next = ph->arr[hash].next;
	ph->arr[hash].next = s;

	return true;

}
bool Del_hash(PHead ph, int key)
{
	int hash = key % HASHSIZE; //得到所在物理下标
	LNode* p = &ph->arr[hash];   //p->arr[hash]是变量,p指向该下标的地址空间,该地址空间存的是链表的第一个节点
	for (; p->next != nullptr; p = p->next)
	{
		if (p->next->data == key)
		{
			LNode* q = p->next;
			p->next = q->next;
			free(q);
			q = nullptr;
			return true;
		}
	}
	return false;
}
struct LNode* Search(PHead ph, int key)
{
	int hash = key % HASHSIZE; //得到所在物理下标
	LNode* p = ph->arr[hash].next; //指针
	for (; p != nullptr; p = p->next)
	{
		if (p->data == key)
		{
			return p;
		}
	}
}
void Show_Hash(PHead ph)
{
		  
    for (int i = 0; i < HASHSIZE; ++i)
		{
	         printf("%3d ", i);
		    struct LNode* p = ph->arr[i].next;
			for (; p != nullptr; p = p->next)
			{
				printf("%d ", p->data);
			}
			printf("\n");
		}
	 
}

测试:

int main()
{
	Head hd;
	Init_listhash(&hd);
	Insert_hash(&hd, 48);
	Insert_hash(&hd, 12);
	Insert_hash(&hd, 37);
	Insert_hash(&hd, 25);
	Insert_hash(&hd, 15);
	Insert_hash(&hd, 16);
	Insert_hash(&hd, 29);
	Insert_hash(&hd, 67);
	Insert_hash(&hd, 56);
	Insert_hash(&hd, 34);
	Insert_hash(&hd, 22);
	Insert_hash(&hd, 47);
	Show_Hash(&hd);
	Del_hash(&hd, 48);
	Show_Hash(&hd);
}

一致性哈希的问题,虚拟节点来解决

普通哈希算法的缺陷:

如果服务器已经不能满足缓存需求,就需要增加服务器数量,假设我们增加了一台缓存服务器,此时如果仍然使用取模,key作为主机数对同一张图片进行缓存,那么这张图片所在的服务器编号必定与原来3台服务器时所在的服务器编号不同,因为除数由3变为了4,最终导致所有缓存的位置都要发生改变,也就是说,当服务器数量发生改变时,所有缓存在一定时间内是失效的,当应用无法从缓存中获取数据时,则会向后端服务器请求数据;同理,假设突然有一台缓存服务器出现了故障,那么我们则需要将故障机器移除,那么缓存服务器数量从3台变为2台,同样会导致大量缓存在同一时间失效,造成了缓存的雪崩,后端服务器将会承受巨大的压力,整个系统很有可能被压垮。为了解决这种情况,就有了一致性哈希算法。

一致哈希的优点:

果简单对服务器数量进行取模,那么当服务器数量发生变化时,会产生缓存的雪崩,从而很有可能导致系统崩溃,而使用一致性哈希算法就可以很好的解决这个问题,因为一致性Hash算法对于节点的增减都只需重定位环空间中的一小部分数据,只有部分缓存会失效,不至于将所有压力都在同一时间集中到后端服务器上,具有较好的容错性和可扩展性。

一致哈希: 一致性哈希算法也是使用取模的方法,但是取模算法是对服务器的数量进行取模,而一致性哈希算法是对 2^32 取模,
具体步骤如下:

  • 步骤一:一致性哈希算法将整个哈希值空间按照顺时针方向组织成一个虚拟的圆环,称为 Hash 环;
  • 步骤二:接着将各个服务器使用 Hash 函数进行哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,从而确定每台机器在哈希环上的位置
  • 步骤三:最后使用算法定位数据访问到相应服务器:将数据key使用相同的函数Hash计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针寻找,第一台遇到的服务器就是其应该定位到的服务器

我们认为在圆圈上存在2^32
个点每个点对应一个值,所以取模的时候即2^32即可
哈希算法将图片映射在哈希环上:hash(图片名称) % 2^32,假设我们有1个数据,映射后的示意图如下:

请添加图片描述
因此如上图,当一个服务器出现故障,不会影响到其他的服务器。

一致哈希和虚拟节点配合使用。解决了数据大量集中在一个服务器的可能性。

请添加图片描述

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

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

相关文章

怎样选择多线程多进程和多协程?

有这么多可以实现并发的方式方法,那么,我们怎么确定在合适的时机采用合适的实现方法呢?这就需要我们对各个实现并发的方式方法有一个全面的概念性的理解,以及他们的内在执行逻辑优缺点有一个清晰的认识! 如下图所示,首先我们需要对单进程、多进程、多线程及多协程之间有…

【代码随想录-链表】两两交换链表中的节点

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

docker-compose Install HertzBeat

HertzBeat前言 HertzBeat 赫兹跳动 是一个拥有强大自定义监控能力,高性能集群,兼容 Prometheus,无需 Agent 的开源实时监控告警系统。 易用友好的开源实时监控告警系统,无需Agent,高性能集群,兼容Prometheus,强大自定义监控能力。​ 集 监控+告警+通知 为一体,支持对…

Redis -- 开篇热身,常用的全局命令

目录 Redis重要文件 启动停止脚本 配置文件 持久化文件存储目录 核心命令 set get 全局命令 keys exists del expire ttl 过期策略是如何实现的 定时器 type 小结 Redis重要文件 启动停止脚本 /usr/bin/redis-benchmark &#xff1a; 用于对Redis做性能基准…

故障诊断 | 一文解决,LSTM长短期记忆神经网络故障诊断(Matlab)

文章目录 效果一览文章概述专栏介绍模型描述源码设计参考资料效果一览 文章概述 故障诊断模型 | Maltab实现LSTM长短期记忆神经网络故障诊断 专栏介绍 订阅【故障诊断】专栏,不定期更新机器学习和深度学习在故障诊断中的应用;订阅

nodejs+vue+mysql大学生心理健康咨询预约评价管理系统1xmao

本课题要求实现一套高校大学生心理咨询管理系统&#xff0c;系统主要包括管理员模块和用户、咨询师模块功能模块。 系统根据现有的管理模块进行开发和扩展&#xff0c;采用面向对象的开发的思想和结构化的开发方法对高校大学生心理咨询管理的现状进行系统调查。采用结构化的分…

力扣之2619.数组原型对象的最后一个元素-JS

Array.prototype.last function () {const a this.length;if (a 0) {return -1;}return this[a - 1]; };const nums [null, {}, 3]; console.log(nums.last());说明&#xff1a; 在 JavaScript 中&#xff0c;Array.prototype 是每个数组对象的原型。通过在 Array.prototy…

故障诊断 | 一文解决,BiLSTM双向长短期记忆神经网络故障诊断(Matlab)

文章目录 效果一览文章概述专栏介绍模型描述源码设计参考资料效果一览 文章概述 故障诊断模型 | Maltab实现BiLSTM双向长短期记忆神经网络故障诊断 专栏介绍 订阅【故障诊断】专栏,不定期更新机器学习和深度学习在故障诊断中的应用;订阅

QT自制软键盘 最完美、最简单、支持中文输入(二)

目录 一、前言 二、本自制虚拟键盘特点 三、中文输入原理 四、组合键输入 五、键盘事件模拟 六、界面 七、代码 7.1 frmKeyBoard 头文件代码 7.2 frmKeyBoard 源文件代码 八、使用示例 九、效果 十、结语 一、前言 由于系统自带虚拟键盘不一定好用&#xff0c;也不一…

《区块链简易速速上手小册》第10章:区块链的未来与趋势(2024 最新版)

文章目录 10.1 区块链的未来展望10.1.1 基础知识10.1.2 主要案例&#xff1a;区块链在金融领域的发展10.1.3 拓展案例 1&#xff1a;区块链在供应链管理中的应用10.1.4 拓展案例 2&#xff1a;区块链在身份管理和隐私保护中的应用 10.2 新兴技术与区块链的融合10.2.1 基础知识1…

大创项目推荐 题目:基于深度学习的中文对话问答机器人

文章目录 0 简介1 项目架构2 项目的主要过程2.1 数据清洗、预处理2.2 分桶2.3 训练 3 项目的整体结构4 重要的API4.1 LSTM cells部分&#xff1a;4.2 损失函数&#xff1a;4.3 搭建seq2seq框架&#xff1a;4.4 测试部分&#xff1a;4.5 评价NLP测试效果&#xff1a;4.6 梯度截断…

力扣hot100 组合总和 回溯 剪枝 组合

Problem: 39. 组合总和 文章目录 思路复杂度&#x1f496; Code 思路 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( n ) O(n) O(n) &#x1f496; Code class Solution{List<List<Integer>> res new ArrayList<>();int x;// 全局targetin…

计算机服务器中了halo勒索病毒怎么办,halo勒索病毒解密

在网络技术飞速发展的今天&#xff0c;越来越多的企业依赖数字化办公&#xff0c;为企业的生产生活提供了极大便利&#xff0c;但网络是一把双刃剑&#xff0c;网络安全威胁无处不在。近期&#xff0c;云天数据恢复中心接到很多企业的求助&#xff0c;企业的计算机服务器中了ha…

九州金榜家庭教育中孩子叛逆怎么办?

青春期是每个孩子成长过程中必经的重要阶段&#xff0c;也是一个充满挑战和矛盾的时期。在这个时期&#xff0c;孩子们就会独立思考事情&#xff0c;有自己的想法&#xff0c;追求自我价值&#xff0c;但由于对世界不能完全认知&#xff0c;具有局限性&#xff0c;他们往往会对…

Flutter开发2:安装Flutter

在本篇博客中&#xff0c;我们将详细介绍如何安装Flutter开发环境。安装Flutter是开始使用Flutter进行跨平台移动应用开发的第一步。让我们开始吧&#xff01; 官方安装文档 步骤1&#xff1a;下载Flutter SDK 打开浏览器&#xff0c;访问Flutter官方网站&#xff1a;https://…

PyTorch深度学习实战(34)——Pix2Pix详解与实现

PyTorch深度学习实战&#xff08;34&#xff09;——Pix2Pix详解与实现 0. 前言1. 模型与数据集1.1 Pix2Pix 基本原理1.2 数据集分析1.3 模型构建策略 2. 实现 Pix2Pix 生成图像小结系列链接 0. 前言 Pix2Pix 是基于生成对抗网络 (Convolutional Generative Adversarial Netwo…

【数据结构 02】队列

一、原理 队列通常是链表结构&#xff0c;只允许在一端进行数据插入&#xff0c;在另一端进行数据删除。 队列的特性是链式存储&#xff08;随机增删&#xff09;和先进先出&#xff08;FIFO&#xff1a;First In First Out&#xff09;。 队列的缺陷&#xff1a; 不支持随机…

【issue-环境】Windows安装Docker

启用Hyper-V以在 Windows 10上创建虚拟机 法一&#xff1a;使用 PowerShell 启用 Hyper-V 以管理员身份打开PowerShell控制台&#xff0c;运行以下命令&#xff1a; Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All法二&#xff1a;通过设置中/控…

海外云手机开辟企业跨境电商新道路

近几年&#xff0c;海外云手机为跨境电商、海外媒体引流、游戏行业等互联网领域注入了蓬勃活力。对于国内跨境电商而言&#xff0c;在亚马逊及其他平台上&#xff0c;短视频引流和社交电商营销成为最为有效的流量来源。如何通过海外云手机的助力&#xff0c;在新兴社交平台为企…

如何保证绩效考核的准确性及公平性?

实施绩效考核是公司为了提高工作绩效&#xff0c;提高员工工作积极性&#xff0c;进而保证公司高效运行的必要手段。但是&#xff0c;在实际管理工作中&#xff0c;很难做到绩效考核的公平、公正&#xff0c;这就会导致员工工作热情不高&#xff0c;绩效考核无法发挥应有的作用…