数据结构与算法(五)

news/2025/2/7 7:01:35/

哈希表(hash)

 

什么是hash?

散列,是把任意长度的输入通过散列算法变换成固定长度输出,该输出的值就是散列值。这种转换是一种压缩映射。映射表达的是一一对应的关系,也就是说,散列值的空间通常会小于输入空间。

const md5 = require('md5-node');
const password = 12345;
console.log(md5(password));

哈希算法不能从结果去推断输出,也就是说哈希算法是不可逆的。

哈希特性

  1. 不可逆,可以作为加密算法存在。   
  2. 计算极快

MD5是不可逆的。对比方式进行校验,(web安全:彩虹表)

哈希用途

  1. 密码
  2. 文件完整校验

数组的不足:

如果是基于索引,数组性能好,但如果基于内容,性能就比较低(插入删除:链表性能好;查询修改:数组性能好)。

举个栗子

有800个好友,设计一个数据结构存储好友信息,名字、邮箱地址

链表查询慢,每次必须从头到尾遍历,用数组需要索引,增加id

const friend = [

{ id:1,name:'张三' ,email:'123@qq.com'},

{ id:2,name:'李四' ,email:'456@qq.com'},

]

有没有一个方法可以将名字直接作为索引提升查询速度?

将字符串name转换成数组的索引,这种东西叫哈希表

哈希表通常是基于数组时限的,但相对于数组,优势:

它可以提供非常快的插入-删除-查找操作(哈希表的结构:数组,但是它和数组不同的是哈希表对于索引一种转换,我们称之为哈希函数)

例如:单词如何转化数字编码?

ASCLL码,编码方式可将字符转化成数字

哈希表是以键值对存储的数据结构,哈希表的键是经过散列函数计算出来的;每一个关键码对应一个值,我们把这种以关键码 -> 值的形式存储数据的数组称为哈希表(散列表)

最简单的哈希函数:把ascll 码加在一起,取模一个数字,最后模出来是多少就是多少(取余数)

class HashTable {constructor(){// 创建哈希表this.table = []; }loseHashCode(key){let hash = 0 ;for(let i=0;i<key.length;i++){// 计算KEY unicode码hash += key[i].charCodeAt();}// 取模 37质数,很大程度上避免碰撞return hash % 37;}// 新增元素put( key ,value ){// 获取keyconst position = this.loseHashCode(key);this.table[position] = value;}// 移除元素remove(key){this.table[this.loseHashCode(key)] = undefined;}// 获取元素get(key){return this.table[this.loseHashCode(key)];}
}
const hashtable = new HashTable();
hashtable.put('小白','123@qq.com');
console.log(hashtable);

哈希覆盖

数组里面,下标相同,数据覆盖,哈希表一样,对于不同要存储的数据经过哈希函数的得到的索引有可能相同。

解决方法:

链地址法

开放地址法:

开放地址法是一种解决数据存放冲突的方法,常用的有线性探测、二次探测和再哈希法

线性探测法

寻找空白的位置来放置冲突的数据项

插入的时候,发现原来index位置已经从存储,则从index+1往后找寻空位置 ,进行插入

查询的时候,查找到空位置就结束,不会查询整个表

删除的时候,不可以设置为NULL。

但是弊端:聚集(一连串填充单元)

当哈希表越来越满时聚集越来越严重,这导致产生非常长的探测长度,后续的数据插入将会非常费时。通常数据超过三分之二满时性能下降严重,因此设计哈希表关键确保不会超过这个数据容量的一半,最多不超过三分之二。

聚集会影响哈希表的性能,无论hi插入、删除、查询

二次探测法

查询优化算法

二次探测是过程是x+1,x+4,x+9,...

二次探测的步数是原始位置相隔的步数的平方

 二次探测可以消除在线性探测中产生的聚集问题,但是二次探测还是会产生一种更明确更细的聚集。二次聚集的产生是在二次探测的基础上产生的现象。例如N个数据经hash函数计算后都映射到到数组下标10,探测第二个数字需要以一步长,第三个数字需要以4步长为单位,第四个数字则需要以九为步长。好在二次探测并不常用,解决聚集问题还是有一种更好的办法:再哈希法。

再哈希法

再哈希是把关键字用不同的哈希函数再做一遍哈希化,用这个结果作为步长,对指定的关键字,探测的步长是不变的,可以说不同的关键字可以使用不同的步长,并且步长可以控制。一般来说,再哈希函数可以采用以下这种:

stepSize=constant-(key%constant);


http://www.ppmy.cn/news/100425.html

相关文章

常量池介绍

什么是“字面量”和“符号引用”和"直接引用" 最近看jvm时遇到了“字面量”和“符号引用”这两个概念&#xff0c;它们被存放在运行时常量池&#xff0c;看了一些博客以后对这两个概念有了初步认识。 字面量可以理解为实际值&#xff0c;int a 8中的8和String a …

vue基于Python的图书商城销售系统qo85w

系统以浏览器/服务器模式即B/S模板式为基础。本系统使用MySQL数据库,利用Python开发的操作系统&#xff1b;主要的功能有个人中心、用户管理、图书资讯管理、图书类型管理、图书信息管理、爬虫管理、留言板管理、系统管理、订单管理等组成。 本文首先介绍了现代化图书销售系统管…

组队系统(一)

游戏进入区服&#xff0c;旋转罗盘&#xff0c;以罗盘方向限定登陆地点&#xff0c;进出游戏罗盘指向不同&#xff0c;遇到的玩家不同&#xff0c;产生游戏社团成员在线的差别。语言聊天&#xff0c;语音转文字&#xff0c;为记录锁定记录。好友群系统&#xff0c;在线玩家&…

贪吃蛇游戏的制作记录

关于蛇的实现代码 #include "snake.h" #include "globalvar.h" #include <graphics.h> int fangXiang 1;//方向 0 右 1 上 2 左 3 下 int snakeHang[100] { 10,11,12,13,14 };//蛇 每节所在行 int snakeLie[100] { 10,10,10,10,10 };//蛇 每节所…

剑指 Offer 11. 旋转数组的最小数字解题思路

文章目录 题目解题思路优化 题目 把一个数组最开始的若干个元素搬到数组的末尾&#xff0c;我们称之为数组的旋转。 给你一个可能存在 重复 元素值的数组 numbers &#xff0c;它原来是一个升序排列的数组&#xff0c;并按上述情形进行了一次旋转。请返回旋转数组的最小元素。…

Dream音频芯片开发概论

1 项目需求 2 开发平台介绍 Dream S.A.S France公司网站&#xff1a;https://www.dream.fr Dream全系列的芯片包含SAM2000 series ICs、SAM3000 series ICs以及SAM5000 series ICs。 SAM5000 series ICs包括 sam5504、sam5704、sam5708、sam5808、sam5716、sam5916。 目前drea…

【牛客算法BM2】 链表内指定区间反转

​ 你好&#xff0c;欢迎来到我的博客&#xff01;作为一名程序员&#xff0c;我经常刷LeetCode题目来提升自己的编程能力。在我的博客里&#xff0c;我会分享一些我自己做过的题目和解题思路&#xff0c;希望能够帮助到大家。今天&#xff0c;我想和大家分享一道挑战性较高的题…

Django学习笔记002之resetfull应用

学习目标&#xff1a; 学习resetfull接口 掌握Django web基础设施 学习内容&#xff1a; 1.学习resetfull接口 简介 人工智能解释&#xff1a; 应用场景 以下是人工智能使用Django框架实现的restfull接口代码&#xff1a; #views.py from django.http import JsonRespon…