散列算法

HashMap、lru、散列表

北战南征 提交于 2020-01-01 10:21:05
HashMap HashMap的数据结构:HashMap实际上是一个数组和链表(“链表散列”)的数据结构。底层就是一个数组结构,数组中的每一项又是一个链表。 hashCode是一个对象的标识,Java中对象的hashCode是一个int类型值。通过hashCode来算出指定数组的索引可以快速定位到要找的对象在数组中的位置,之后再遍历链表找到对应值,理想情况下时间复杂度为O(1),并且不同对象可以拥有相同的hashCode(hash碰撞)。发生碰撞后会把相同hashcode的对象放到同一个链表里,但是在数组大小不变的情况下,存放键值对越多,查找的时间效率也会降低 扩容可以解决该问题,而负载因子决定了什么时候扩容,负载因子是已存键值对的数量和总的数组长度的比值。默认情况下负载因子为0.75,我们可在初始化HashMap的时候自己修改。阀值 = 当前数组长度✖负载因子 hashmap中默认负载因子为0.75,长度默认是16,默认情况下第一次扩容判断阀值是16 ✖ 0.75 = 12;所以第一次存键值对的时候,在存到第13个键值对时就需要扩容了,变成16X2=32。 put流程 对key hash,二次hash,hash扰乱函数,减少hash碰撞 int hash(Object key) { int h = key.hashCode(); return (h ^ (h >>> 16)) &

彩虹表

孤街浪徒 提交于 2019-12-29 23:42:43
彩虹表是一个用于 加密散列函数 逆运算的预先计算好的表, 为破解密码的散列值(或称哈希值、微缩图、摘要、指纹、哈希密文)而准备。一般主流的彩虹表都在100G以上。 这样的表常常用于恢复由有限集字符组成的固定长度的纯文本密码。这是空间/时间替换的典型实践, 比每一次尝试都计算哈希的暴力破解处理时间少而储存空间多,但却比简单的对每条输入散列翻查表的破解方式储存空间少而处理时间多。使用加salt的KDF函数可以使这种攻击难以实现。彩虹表是 马丁·赫尔曼 早期提出的简单算法的应用。 来源: https://www.cnblogs.com/xinhua219/p/10092492.html

Thinking in Java:容器深入研究

て烟熏妆下的殇ゞ 提交于 2019-12-27 04:56:07
1.虚线框表示Abstract类,图中大量的类的名字都是以Abstract开头的,它们仅仅是部分实现了特定接口的工具,因此创建时能够选择从Abstract继承。 Collections中的实用方法:挑几个经常使用的: 1. reverse(List):逆转次序 2. rotate(List,int distance)全部元素向后移动distance个位置,将末尾元素循环到前面来(用了三次reverse) 3.sort(List,Comparator) 排序,可依照自己的Comparator 4.copy(List dest,List src) 复制元素(引用) 5.fill(List,T x)同Arrays一样。复制的是同一引用 6.disjoint(Collection。Collection) 两个集合没有不论什么元素时返回ture 7.frequency(Collection, Object x)返回Collection中等于x的元素个数 8.binarySearch()折半查找(要求有序) Collection的功能方法: boolean add(T) 可选方法 。若没将參数加入进容器,则false boolean addAll(Collection ) 可选方法 ,仅仅要加入了随意元素就true void clear() 可选方法 boolean contains(T)

java数组、List、Set、Map

陌路散爱 提交于 2019-12-25 17:53:10
数组是 Java 语言内置的类型,除此之外,Java有多种保存对象引用的方式。Java类库提供了一套相当完整的容器类,使用这些类的方法可以保存和操纵对象。下面分别进行讨论,在研究Java容器类之前,先了解一下Java数组的基本功能和特性。 1. 数组的基本特性 数组与 其它 种类的容器(List/Set/Map)之间的区别在于效率、确定的类型和保存基本类型数据的能力。数组是一种高效的存储和随机访问对象引用序列的方式,使用数组可以快速的访问数组中的元素。但是当创建一个数组对象(注意和对象数组的区别)后,数组的大小也就固定了,当数组空间不足的时候就再创建一个新的数组,把旧的数组中所有的引用复制到新的数组中。 Java中的数组和容器都需要进行边界检查,如果越界就会得到一个RuntimeException异常。这点和C++中有所不同,C++中vector 的操作符[]不会做边界检查,这在速度上会有一定的提高,Java的数组和容器会因为时刻存在的边界检查带来一些性能上的开销。 Java中通用的容器类不会以具体的类型来处理对象,容器中的对象都是以Object类型处理的,这是Java中所有类的基类。另外,数组可以保存基本类型,而容器不能,它只能保存任意的Java对象。 一般情况下,考虑到效率与类型检查,应该尽可能考虑使用数组。如果要解决一般化的问题,数组可能会受到一些限制

哈希结构及应用

拟墨画扇 提交于 2019-12-25 17:45:36
哈希 可以不经过任何比较,一次直接从表中得到搜索的元素,像那些 vecotor ,list ,AVL 呀,都是必须经过比较之后才能找到元素的,所以哈希在查找元素方面时间复杂度是O(1) 那它是怎么做到的呢?其实是通过某种函数使元素的存储位置与它的关键码之间建立一种映射关系 哈希表的实现主要是 构造哈希 和 处理哈希冲突 两方面 我们先讨论如何构造,最后讨论如何处理哈希冲突 对于构造哈希来说,常见的哈希函数包括 直接地址法 , 除留余数法 ,平方取中法,折叠法,随机数法… 那么选择什么样的哈希函数主要取决于关键字的特点 (1) 如果事先知道关键字的分布情况,并且发现这些关键字很小,而且连续,那么就可以采用 直接地址法或者除留余数法 直接地址法 :取关键字的某个线性函数为散列地址:Hash(Key)= A * key + B 除留余数法 :假如散列表中允许的地址数为 m ,取一个不大于 m 且最接近 m 的一个质数 p 作为除数 ,按照哈希函数 Hash(key) = key % p (p<=m),将关键码转换成哈希地址 (2) 如果不知道关键的分布,且这些关键字的位数也不大,就可以采用平方取中法。 平方取中法:对一个数平方后取出中间的数字作为哈希地址,这种方法适合于不知道关键字的分布且位数也不是很大的情况 (3) 如果不知道关键字的分布,且这些关键字的位数很大的情况,可以采用折叠法。

Hash算法

人走茶凉 提交于 2019-12-24 00:56:04
  Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的 消息摘要 的函数。   HASH主要用于信息安全领域中加密算法,它把一些不同长度的信息转化成杂乱的128位的编码,这些编码值叫做HASH值. 也可以说,hash就是找到一种数据内容和数据存放地址之间的映射关系 基本概念    * 若结构中存在和关键字K相等的记录,则必定在f(K)的存储位置上。由此,不需比较便可直接取得所查记录。称这个对应关系f为 散列函数 (Hash function),按这个思想建立的表为 散列表 。   * 对不同的关键字可能得到同一散列地址,即key1≠key2,而f(key1)=f(key2),这种现象称冲突。具有相同函数值的关键字对该散列函数来说称做同义词。综上所述,根据散列函数H(key)和处理冲突的方法将一组关键字映象到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“象” 作为记录在表中的存储位置,这种表便称为散列表,这一映象过程称为散列造表或散列,所得的存储位置称散列地址。   *

【算法笔记】散列表(上)

こ雲淡風輕ζ 提交于 2019-12-15 03:35:20
散列表(上) 1.如何理解散列思想? 2.有哪些散列函数? 1 散列函数的定义 2 散列函数设计的基本要求 3.散列冲突的解决方法是什么? 1. 开放寻址法 2 链表法 4 Word 文档中单词拼写检查功能是如何实现的? 5. 总结 1.如何理解散列思想? 散列表的英文叫“Hash Table”,我们平时也叫它“哈希表”或者“Hash 表”; 散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。可以说,如果没有数组,就没有散列表。 散列表使用的是数组支持按照下标随机访问的时候,时间复杂度是O(1)的特性; 通过散列函数把元素的键值映射为下标,然后将数据存储在数组中对应的下标的位置; 当按照键值查询元素的时候,用同样的散列函数,间键值转化为数组下标,从对应的数组下标的位置取数据; 2.有哪些散列函数? 1 散列函数的定义 散列函数在散列表中起着非常关键的作用。 散列函数,顾名思义,它是一个函数。可以把它定义成 hash(key),其中 key 表示元素的键值,hash(key) 的值表示经过散列函数计算得到的散列值。 2 散列函数设计的基本要求 散列函数计算得到的散列值是一个非负整数; 如果 key1 = key2,那 hash(key1) == hash(key2); 如果 key1 ≠ key2,那 hash(key1) ≠ hash

hashcode的理解

不想你离开。 提交于 2019-12-10 08:41:06
============================================================ 如何理解hashCode的作用: ============================================================ 以java.lang.Object来理解,JVM每new一个Object,它都会将这个Object丢到一个Hash哈希表中去,这样的话,下次做Object的比较或者取这个对象的时候,它会根据对象的hashcode再从Hash表中取这个对象。这样做的目的是提高取对象的效率。具体过程是这样: 1.new Object(),JVM根据这个对象的Hashcode值,放入到对应的Hash表对应的Key上,如果不同的对象确产生了相同的hash值,也就是发生了Hash key相同导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将所有产生相同hashcode的对象放到这个单链表上去,串在一起。 2.比较两个对象的时候,首先根据他们的hashcode去hash表中找他的对象,当两个对象的hashcode相同,那么就是说他们这两个对象放在Hash表中的同一个key上,那么他们一定在这个key上的链表上。那么此时就只能根据Object的equal方法来比较这个对象是否equal。当两个对象的hashcode不同的话

深入分析 JDK8 中 HashMap 的原理、实现和优化

久未见 提交于 2019-12-10 05:09:16
HashMap 可以说是使用频率最高的处理键值映射的数据结构,它不保证插入顺序,允许插入 null 的键和值。本文采用 JDK8 中的源码,深入分析 HashMap 的原理、实现和优化。首发于微信公众号 顿悟源码 . 1. 基本结构 HashMap 基于散列表实现,使用 拉链法 处理碰撞,在 JDK8 中,当链表长度大于 8 时转为 红黑树 存储,基本结构如下: HashMap 有一个 Node<K,V>[] table 字段,即哈希桶数组,数组元素是 Node 对象,结构定义如下: static class Node<K,V> implements Map.Entry<K,V> { final int hash; // 用于计算数组索引 final K key; V value; Node<K,V> next; // 后继节点,下一个 Node Node(int hash, K key, V value, Node<K,V> next) { ... } ... } 哈希桶数组会在首次使用时初始化,默认大小是 16,并根据需要调整大小,且长度总是 2 的次幂。如果构造函数设置的初始容量不是 2 的次幂,那么使用以下方法返回一个 大于且最靠近 它的 2 的次幂的值: static final int tableSizeFor(int cap) { int n = cap - 1; n

MD5 + salt 的加密算法

筅森魡賤 提交于 2019-12-09 21:26:07
MD5 + salt 的加密算法 对于这次泄露门事件,因为本人的账号(CSDN)有在内所以很想说shit…同时觉得csdn真丢脸… 一直想不到csdn会用明文保存密码,上次忘记密码邮箱直接收到了密码的网站大概在是十年前的某注册用户不到十个的小网站吧. 回到重点,我们知道,如果直接对密码进行散列,那么黑客可以对通过获得这个密码散列值,然后通过查散列值字典(例如MD5密码破解网站),得到某用户的密码。 加Salt可以一定程度上解决这一问题。所谓加Salt方法,就是加点“佐料”。其基本想法是这样的:当用户首次提供密码时(通常是注册时),由系统自动往这个密码里撒一些“佐料”,然后再散列。而当用户登录时,系统为用户提供的代码撒上同样的“佐料”,然后散列,再比较散列值,已确定密码是否正确。 这里的“佐料”被称作“Salt值”,这个值是由系统随机生成的,并且只有系统知道。这样,即便两个用户使用了同一个密码,由于系统为它们生成的salt值不同,他们的散列值也是不同的。即便黑客可以通过自己的密码和自己生成的散列值来找具有特定密码的用户,但这个几率太小了(密码和salt值都得和黑客使用的一样才行)。 下面以PHP示例,讲解md5($pass.$salt)加密函数。 <?php function hash($a) { $salt=”Random_KUGBJVY”; //定义一个salt值