哈希查找

解决哈希冲突的三种方法(拉链法、开放地址法、再散列法)

孤街醉人 提交于 2019-12-21 11:48:48
上篇博客我们说到了,什么是哈希冲突,其实就是再采用哈希函数对输入域进行映射到哈希表的时候,因为哈希表的位桶的数目远小于输入域的关键字的个数,所以,对于输入域的关键字来说,很可能会产生这样一种情况,也就是,一个关键字会映射到同一个位桶中的情况,这种情况就就叫做哈希冲突,解决哈希冲突的有三种方案,一种叫做拉链法(也叫作链接法、链地址法,一个意思),另外三种分别为开发地址法和再散列法。 一、拉链法 上篇博文我们举的例子,HashMap,HashSet其实都是采用的拉链法来解决哈希冲突的,就是在每个位桶实现的时候,我们采用链表(jdk1.8之后采用链表+红黑树)的数据结构来去存取发生哈希冲突的输入域的关键字(也就是被哈希函数映射到同一个位桶上的关键字)。首先来看使用拉链法解决哈希冲突的几个操作: ①插入操作:在发生哈希冲突的时候,我们输入域的关键字去映射到位桶(实际上是实现位桶的这个数据结构,链表或者红黑树)中去的时候,我们先检查带插入元素x是否出现在表中,很明显,这个查找所用的次数不会超过装载因子(n/m:n为输入域的关键字个数,m为位桶的数目),它是个常数,所以插入操作的最坏时间复杂度为O(1)的。 ②查询操作:和①一样,在发生哈希冲突的时候,我们去检索的时间复杂度不会超过装载因子,也就是检索数据的时间复杂度也是O(1)的 ③删除操作

使用哈希加盐法来为密码加密(补充JAVA的实现)

南楼画角 提交于 2019-12-20 03:23:04
使用哈希加盐法来为密码加密 转自:http://www.cnblogs.com/jfzhu/p/4023439.html 转载请注明出处 (一)为什么要用哈希函数来加密密码 如果你需要保存密码(比如网站用户的密码),你要考虑如何保护这些密码数据,象下面那样直接将密码写入数据库中是极不安全的,因为任何可以打开数据库的人,都将可以直接看到这些密码。 解决的办法是将密码加密后再存储进数据库,比较常用的加密方法是使用哈希函数(Hash Function)。哈希函数的具体定义,大家可以在网上或者相关书籍中查阅到,简单地说,它的特性如下: (1)原始密码经哈希函数计算后得到一个哈希值 (2)改变原始密码,哈希函数计算出的哈希值也会相应改变 (3) 同样的密码,哈希值也是相同的 (4) 哈希函数是单向、不可逆的。也就是说从哈希值,你无法推算出原始的密码是多少 有了哈希函数,我们就可以将密码的哈希值存储进数据库。用户登录网站的时候,我们可以检验用户输入密码的哈希值是否与数据库中的哈希值相同。 由于哈希函数是不可逆的,即使有人打开了数据库,也无法看到用户的密码是多少。 那么存储经过哈希函数加密后的密码是否就是安全的了呢?我们先来看一下几种常见的破解密码的方法。 (二)几种常见的破解密码的方法 最简单、常见的破解方式当属字典破解(Dictionary Attack)和暴力破解(Brute Force

hashmap实现及哈希冲突

寵の児 提交于 2019-12-18 10:02:05
原文: https://www.cnblogs.com/peizhe123/p/5790252.html HashMap 采用一种所谓的“Hash 算法”来决定每个元素的存储位置。当程序执行 map.put(String,Obect)方法 时,系统将调用String的 hashCode() 方法得到其 hashCode 值——每个 Java 对象都有 hashCode() 方法,都可通过该方法获得它的 hashCode 值。得到这个对象的 hashCode 值之后,系统会根据该 hashCode 值来决定该元素的存储位置。源码如下: Java代码 public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; //判断当前确定的索引位置是否存在相同hashcode和相同key的元素,如果存在相同的hashcode和相同的key的元素,那么新值覆盖原来的旧值,并返回旧值。 //如果存在相同的hashcode

算法打基础——HashⅡ: 全域哈希与完美哈希

狂风中的少年 提交于 2019-12-18 03:29:53
这一节涉及数学超级多,各种数论知识,各种不明觉厉! 看了几遍,才勉强看懂一些,所以这 篇稍微简单的介绍着两种hash table, 免得瞎说说错了。 这一讲的主要知识点是: 1. 全域哈希及构造 2. 完美哈希 1. 全域哈希及构造 介绍全域哈希之前,要先讨论一下普通哈希的一个缺点。 举个charles举得那个例子:如果你 和一个竞争对手同时为一家公司做compiler的symbol table, 公司要求你们代码共享 (o(╯□╰)o),你们做好后公司评判的标准就是 你俩互相提供一些测试样例,谁的效率高就买 谁的。 然后, 普通哈希的缺点 就出来了:对任意的hash函数h,总存在一组keys,使得 , 对某个槽i。即我总可以找到一组键值,让他们都映射到同一个槽里面,这样效率 就跟离链表差不多了 解决的思想就是:独立于键值, 随机 的选择hash 函数。这就跟快排中为避免最差情况时随机化 版本差不多。但是选取hash function的全局域是不能乱定的,否则也打不到理想的性能。 下面就给出全域哈希的定义: 设U是key的全局域, 设\(\mathcal{H}\) 是哈希函数的有限集合,每一个都是将U映射到 {0,1,..,m-1},即table的槽内。 如果对所有不等的\(x,y\in U\),有 换句话说,就是对于任意的不相等key的x和y, 从哈希函数集中选择一个哈希函数

哈希情史知多少

感情迁移 提交于 2019-12-16 10:49:04
——日拱一卒,不期而至! 简介 hash是我们工作中经常听到的词,比如哈希表、哈希函数、hashCode、HashTable、HashMap等等,那么它们之间到底有怎样的爱恨情仇呢?来一起看一看吧~~ 数组 讲哈希表之前,我们先来看看数据结构的鼻祖——数组。 数组比较简单,我就不多说了,大家都会都懂,见下图。 数组的下标一般从0开始,依次往后存储元素,查找元素也是一样,只能从头(或从尾)依次查找元素。 比如,要查找4这个元素,从头开始查找的话需要查找3次,从尾的话也需要2次。 早期的哈希表 上面讲了数组的缺点,查找某个元素只能从头或者从尾依次查找元素,直到匹配为止,它的均衡时间复杂是O(n)。 那么,利用数组有没有什么方法可以快速的查找元素呢? 聪明的程序员哥哥们想到一种方法,通过哈希函数计算元素的值,用这个值确定元素在数组中的位置,这样时间复杂度就能缩短到O(1)了。 比如,有5个元素分别为3、5、4、1,把它们放入到数组之前先通过哈希函数计算位置,精确放置,而不是像简单数组那样依次放置元素。 假如,这里申请的数组长度为8,我们可以造这么一个哈希函数为hash(x) = x % 8,那么最后的元素就变成了下图这样: 这时候我们再查找4这个元素,先算一下它的hash值为hash(4) = 4 % 8 = 4,所以直接返回4号位置的元素就可以了。 进化的哈希表 事情看着挺完美,但是

Redis源码剖析--哈希t_hash

馋奶兔 提交于 2019-12-15 18:42:15
不知不觉,从第一篇写Redis源码分析开始,已经过了快一个月了,想想自己的进度,简直慢的吓人啊,这样下去不行,后面得加快脚步了。今天分析的是Redis的又一个数据类型—哈希,哈希键的底层编码形式有OBJ_ENCODING_ZIPLIST和OBJ_ENCODING_HT两种,其中,前者的底层数据结构为压缩列表,后者的底层数据结构为字典。如有对这两个结构不清楚的,可以点击跳转去温故复习一下。 Hash概述 前面我们提到,Redis对于其五个对用户公开的数据类型统一采用RedisObject管理。Hash类型只需要修改encoding字段就能表示该对象为一个哈希对象。为了便于大家理解,我还是不厌其烦的先罗列出RedisObject的结构体定义。 typedef struct redisObject { unsigned type:4; // hash类型 unsigned encoding:4; // hash结构,此字段为OBJ_ENCODING_ZIPLIST或OBJ_ENCODING_HT unsigned lru:LRU_BITS; // 上一次操作的时间 int refcount; // 引用计数,便于内存管理 void *ptr; // 指向底层的数据结构 } robj; 如果底层编码是ziplist的话,hash键按照如下方式排列

一致性哈希算法的原理与实现

三世轮回 提交于 2019-12-15 03:11:44
1 概述 1.1 传统哈希(硬哈希) 分布式系统中,假设有 n 个节点,传统方案使用 mod(key, n) 映射数据和节点。 当扩容或缩容时(哪怕只是增减1个节点),映射关系变为 mod(key, n+1) / mod(key, n-1),绝大多数数据的映射关系都会失效。 1.2 一致性哈希(Consistent Hashing) 1997年,麻省理工学院(MIT)的 David Karger 等6个人发布学术论文《Consistent hashing and random trees: distributed caching protocols for relieving hot spots on the World Wide Web(一致性哈希和随机树:用于缓解万维网上热点的分布式缓存协议)》,对于 K 个关键字和 n 个槽位(分布式系统中的节点)的哈希表,增减槽位后,平均只需对 K/n 个关键字重新映射。 1.3 哈希指标 评估一个哈希算法的优劣,有如下指标,而一致性哈希全部满足: 均衡性(Balance):将关键字的哈希地址均匀地分布在地址空间中,使地址空间得到充分利用,这是设计哈希的一个基本特性。 单调性(Monotonicity): 单调性是指当地址空间增大时,通过哈希函数所得到的关键字的哈希地址也能映射的新的地址空间,而不是仅限于原先的地址空间。或等地址空间减少时

哈希情史知多少

时光毁灭记忆、已成空白 提交于 2019-12-14 08:44:21
——日拱一卒,不期而至! 简介 hash是我们工作中经常听到的词,比如哈希表、哈希函数、hashCode、HashTable、HashMap等等,那么它们之间到底有怎样的爱恨情仇呢?来一起看一看吧~~ 数组 讲哈希表之前,我们先来看看数据结构的鼻祖——数组。 数组比较简单,我就不多说了,大家都会都懂,见下图。 数组的下标一般从0开始,依次往后存储元素,查找元素也是一样,只能从头(或从尾)依次查找元素。 比如,要查找4这个元素,从头开始查找的话需要查找3次,从尾的话也需要2次。 早期的哈希表 上面讲了数组的缺点,查找某个元素只能从头或者从尾依次查找元素,直到匹配为止,它的均衡时间复杂是O(n)。 那么,利用数组有没有什么方法可以快速的查找元素呢? 聪明的程序员哥哥们想到一种方法,通过哈希函数计算元素的值,用这个值确定元素在数组中的位置,这样时间复杂度就能缩短到O(1)了。 比如,有5个元素分别为3、5、4、1,把它们放入到数组之前先通过哈希函数计算位置,精确放置,而不是像简单数组那样依次放置元素。 假如,这里申请的数组长度为8,我们可以造这么一个哈希函数为hash(x) = x % 8,那么最后的元素就变成了下图这样: 这时候我们再查找4这个元素,先算一下它的hash值为hash(4) = 4 % 8 = 4,所以直接返回4号位置的元素就可以了。 进化的哈希表 事情看着挺完美,但是

哈希情史知多少

纵饮孤独 提交于 2019-12-14 00:53:40
——日拱一卒,不期而至! 简介 hash是我们工作中经常听到的词,比如哈希表、哈希函数、hashCode、HashTable、HashMap等等,那么它们之间到底有怎样的爱恨情仇呢?来一起看一看吧~~ 数组 讲哈希表之前,我们先来看看数据结构的鼻祖——数组。 数组比较简单,我就不多说了,大家都会都懂,见下图。 数组的下标一般从0开始,依次往后存储元素,查找元素也是一样,只能从头(或从尾)依次查找元素。 比如,要查找4这个元素,从头开始查找的话需要查找3次,从尾的话也需要2次。 早期的哈希表 上面讲了数组的缺点,查找某个元素只能从头或者从尾依次查找元素,直到匹配为止,它的均衡时间复杂是O(n)。 那么,利用数组有没有什么方法可以快速的查找元素呢? 聪明的程序员哥哥们想到一种方法,通过哈希函数计算元素的值,用这个值确定元素在数组中的位置,这样时间复杂度就能缩短到O(1)了。 比如,有5个元素分别为3、5、4、1,把它们放入到数组之前先通过哈希函数计算位置,精确放置,而不是像简单数组那样依次放置元素。 假如,这里申请的数组长度为8,我们可以造这么一个哈希函数为hash(x) = x % 8,那么最后的元素就变成了下图这样: 这时候我们再查找4这个元素,先算一下它的hash值为hash(4) = 4 % 8 = 4,所以直接返回4号位置的元素就可以了。 进化的哈希表 事情看着挺完美,但是

哈希情史知多少

倾然丶 夕夏残阳落幕 提交于 2019-12-13 21:50:58
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> <p align="right">——日拱一卒,不期而至!</p> 简介 hash是我们工作中经常听到的词,比如哈希表、哈希函数、hashCode、HashTable、HashMap等等,那么它们之间到底有怎样的爱恨情仇呢?来一起看一看吧~~ 数组 讲哈希表之前,我们先来看看数据结构的鼻祖——数组。 数组比较简单,我就不多说了,大家都会都懂,见下图。 数组的下标一般从0开始,依次往后存储元素,查找元素也是一样,只能从头(或从尾)依次查找元素。 比如,要查找4这个元素,从头开始查找的话需要查找3次,从尾的话也需要2次。 早期的哈希表 上面讲了数组的缺点,查找某个元素只能从头或者从尾依次查找元素,直到匹配为止,它的均衡时间复杂是O(n)。 那么,利用数组有没有什么方法可以快速的查找元素呢? 聪明的程序员哥哥们想到一种方法,通过哈希函数计算元素的值,用这个值确定元素在数组中的位置,这样时间复杂度就能缩短到O(1)了。 比如,有5个元素分别为3、5、4、1,把它们放入到数组之前先通过哈希函数计算位置,精确放置,而不是像简单数组那样依次放置元素。 假如,这里申请的数组长度为8,我们可以造这么一个哈希函数为hash(x) = x % 8,那么最后的元素就变成了下图这样: 这时候我们再查找4这个元素