哈希查找

【数据结构】哈希表及其模拟实现

十年热恋 提交于 2020-03-16 18:37:19
一.哈希及其概念 通过一定的哈希函数,确定元素的存储位置。搜索效率较高,为O(1) 负载因子:存储元素个数/总表格长度 若大于一定值需要扩容 二.常见的哈希函数 直接定址法:hashfunc(date)=A*date+B;【A,B为常数】 除留余数法:hashfunc(date)=date%capacity【capacity为表格容量】 平方取中法:将数据平方后取中间三位。 折叠法:例 12345 12+34+5=51 三.哈希冲突 不同元素计算出的存储位置(哈希地址)相同 四.解决哈希冲突 1.前期需有效减少哈希冲突的发生--------》哈希函数设计要合理 哈希函数的值域必须在表格范围内 哈希函数要尽可能使元素分布均匀 哈希函数要尽可能简单 2.发生哈希冲突后如何解决 闭散列:从哈希冲突的位置,找下一个空余位置插入元素 开散列:将哈希冲突的元素按链表的形式挂在结点位置 五.闭散列 从哈希冲突的位置,找下一个空余位置插入元素。寻找方式有两种,线性探测和二次探测。 1.线性探测 直接向后+1查找。 优点:简单 缺点:容易造成数据堆积。一个冲突造成很多数据都冲突。 2.二次探测 H(i)=H0+i^2; 或者H(i)=H0- i^2; 优点:解决了数据堆积问题 缺点:可能要查找多次 3.初始化,需设置标志位【EX,EM,DE】 DE需要的原因,此位置不可以插入元素,也不可设置为EM

20200311——java面试集合 深入HashMap 二

扶醉桌前 提交于 2020-03-12 03:53:43
ArrayList、Vector、LinkedList的存储性能和特性 ArrayList 和Vector都是使用数组方式存储数据 ,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector中的方法由于添加了synchronized修饰,因此Vector是线程安全的容器,但性能上较ArrayList差,因此已经是Java中的遗留容器。 LinkedList使用 双向链表 实现存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,内存的利用率更高), 按序号索引数据需要进行前向或后向遍历 ,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。 TreeMap的底层实现 TreeMap 的实现就是红黑树数据结构,也就说是一棵自平衡的排序二叉树,这样就可以保证当需要快速检索指定节点。 红黑树的插入、删除、遍历时间复杂度都为O(lgN),所以性能上低于哈希表。但是哈希表无法提供键值对的有序输出,红黑树因为是排序插入的,可以按照键的值的大小有序输出。红黑树性质: 性质1:每个节点要么是红色,要么是黑色。 性质2:根节点永远是黑色的。 性质3:所有的叶节点都是空节点(即 null),并且是黑色的。 性质4

Java与C ++中的哈希

余生颓废 提交于 2020-03-07 20:06:59
Java和C ++在语法上有些相似,但是随着时间的流逝而发生了变化。Java受到C ++的宽松启发,但最初并未采用C ++的模板结构,也不需要C ++的头文件/内容文件分离,并且当然,它使用JVM并编译为字节码而不是机器码。 从那时起,这两种语言在某种程度上融合了起来-它们遵循相似的编码准则,支持Lamda构造,泛型/模板,循环语法的多个相同形式,等等。但是,现代用途肯定存在差异。C ++模板支持专业化,而Java泛型支持类型限制。它们也具有相似的基本集合类型。 哈希表,哈希图和类似类型的数据结构,这些数据结构允许通过唯一键进行索引,但是该索引是以非常特定的方式实现的。现在,任何关联的容器类型都可以让你通过特定键访问数据。例如,你可以使用链表作为存储结构,也可以使用双链表或二叉树。哈希表本质上使用数组,但是该数组由哈希值索引。 Java 具有作为类的基本关联容器类型 java.util.HashMap 。 C ++ 有 std::unordered_map 。 基于哈希的容器在数据存储方面具有明显的优势。当使用具有低冲突可能性的哈希生成器时,两个容器( HashMap 和 unordered_map )都具有 O ( 1 )查找性能。碰撞的可能性越大,容器的性能就越接近 O ( n ),其中 n 是存储在容器中的元素数。这两个容器也都使用标准的哈希函数 -Java 需要键来实现

并发系列(2)之 ThreadLocal 详解

*爱你&永不变心* 提交于 2020-02-25 08:14:15
本文将主要结合源码讲述 ThreadLocal 的使用场景和内部结构,以及 ThreadLocalMap 的内部结构;另外在阅读文本之前只好先了解一下引用和 HashMap 的相关知识,可以参考 Reference 框架概览 、 Reference 完全解读 、 HashMap 相关 ; 一、使用场景 通常情况下避免多线程问题有三种方法: 不使用共享状态变量; 状态变量为不可变的; 访问共享变量时使用同步; 而 ThreadLocal 则是通过每个线程独享状态变量的方式,即不使用共享状态变量,来消除多线程问题的,例如: @Slf4j public class TestThreadlocal { private static ThreadLocal<String> local = ThreadLocal.withInitial(() -> "init"); public static void main(String[] args) throws InterruptedException { Runnable r = new TT(); new Thread(r, "thread1").start(); Thread.sleep(2000); new Thread(r, "thread2").start(); log.info("exit"); } private static

哈希表

孤街醉人 提交于 2020-02-23 10:50:38
1.什么是哈希表? 哈希表:根据设定的哈希函数H(key)和处理冲突的方法将一组关键字映射到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“像”作为记录在表中的存储位置,这种表便称为哈希表,这一映像过程称为哈希造表或散列,所得的存储位置称哈希地址或散列地址。 2.哈希表的特点: (1)哈希函数是一个映射,因此哈希函数的设定很灵活,只要使得任何关键字由此所得的哈希函数值都落在表允许的长度范围内即可; (2)对不同的关键字可能得到同一哈希地址,即key1≠key2,而f(key1)=f(key2),这种现象叫“冲突”。“冲突”只能减少不能避免,因为关键字数量巨大,而地址值只能为哈希表中的值,数量较小。 3.常用的构造哈希函数 1.直接定址法 取关键字的某个线性函数值为哈希地址。即:H(key)=key或H(key)=a*key+b,实际中很少用。 2.数字分析法 对关键字进行分析,尽量找随机性大的数字。 3.平方取中法 取关键字平方后的中间几位为哈希地址,这是一种较常用的构造哈希函数的方法。取的位数由表长决定。 4.折叠法 将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的折叠和(舍去进位)作为哈希地址,这方法称为折叠法。关键字位数很多,而且关键字中每一位上数字分布大致相同时,可以采用折叠法得到哈希地址。 5.除留余数法

(转)查找算法:哈希查找

廉价感情. 提交于 2020-02-23 10:31:42
什么是哈希查找呢?在弄清楚什么是哈希查找之前,我们要弄清楚哈希技术,哈希技术是在记录的存储位置和记录的 key 之间建立一个确定的映射 f(),使得每个 key 对应一个存储位置 f(key)。若查找集合中存在这个记录,则必定在 f(key) 的位置上。哈希技术既是一种存储方法,也是一种查找方法。 六种哈希函数 f(key) 的构造方法: 1、直接定址法 哈希地址:f(key) = a*key+b (a,b为常数) 这种方法的优点是:简单,均匀,不会产生冲突。但是需要事先知道 key 的分布情况,适合查找表较小并且连续的情况。 2、数字分析法 比如我们的11位手机号码“136xxxx5889”,其中前三位是接入号,一般对应不同运营公司的子品牌,如130是联通如意通,136是移动神州行等等。中间四位表示归属地。最后四位才是用户号。 若我们现在要存储某家公司员工登记表,如果用手机号码作为 key,那么极有可能前7位都是相同的,所以我们选择最后四位作为 f(key) 就是不错的选择。 3、平方取中法 故名思义,比如 key 是1234,那么它的平方就是1522756,再抽取中间的3位就是227作为 f(key) 。 4、折叠法 折叠法是将 key 从左到右分割成位数相等的几个部分(最后一部分位数不够可以短些),然后将这几部分叠加求和,并按哈希表的表长,取后几位作为 f(key) 。

数据结构与算法18—哈希表(散列表)

≯℡__Kan透↙ 提交于 2020-02-23 10:29:44
哈希表的概念 哈希表(Hash Table)是一种特殊的数据结构,它最大的特点就是可以快速实现查找、插入和删除。 我们知道,数组的最大特点就是:寻址容易,插入和删除困难;而链表正好相反,寻址困难,而插入和删除操作容易。那么如果能够结合两者的优点,做出一种寻址、插入和删除操作同样快速容易的数据结构,那该有多好。这就是哈希表创建的基本思想,而实际上哈希表也实现了这样的一个“夙愿”,哈希表就是这样一个集查找、插入和删除操作于一身的数据结构。 哈希表 (Hash Table):也叫散列表,是根据关键码值(key-value)而直接进行访问的数据结构,也就是我们常用到的map。 哈希函数 :也称为是散列函数,是Hash表的映射函数,它可以把任意长度的输入变换成固定长度的输出,该输出就是 哈希值 。哈希函数能使对一个数据序列的访问过程变得更加迅速有效,通过哈希函数,数据元素能够被很快的进行定位。 哈希表和哈希函数的标准定义:若关键字为k,则其值存放在h(k)的存储位置上。由此,不需比较便可直接取得所查记录。称这个对应关系f为哈希函数,按这个思想建立的表为哈希表。 设计出一个简单、均匀、存储利用率高的散列函数是散列技术中最关键的问题。 但是,一般散列函数都面临着冲突的问题。两个不同的关键字,由于散列函数值相同,因而被映射到同一表位置上。该现象称为冲突(Collision)或碰撞

数据结构---->哈希表

浪尽此生 提交于 2020-02-23 10:23:25
一、哈希表 哈希表又称散列表。 哈希表存储的基本思想是:以数据表中的每个记录的关键字k为自变量,通过一种函数H(k)计算出函数值。把这个值解释为一块连续存储空间(即数组空间)的单元地址(即下标),将该记录存储到这个单元中。 在此称该函数H为哈希函数或散列函数。按这种方法建立的表称为哈希表或散列表。 例如,要将关键字值序列(3,15,22,24),存储到编号为0到4的表长为5的哈希表中。 计算存储地址的哈希函数可取除5的取余数算法H(k)=k% 5。则构造好的哈希表如图所示。 理想情况下,哈希函数在关键字和地址之间建立了一个一一对应关系,从而使得查找只需一次计算即可完成。由于关键字值的某种随机性,使得这种一一对应关系难以发现或构造。因而可能会出现不同的关键字对应一个存储地址。即 k1≠k2 , 但 H(k1)=H(k2 ), 这种现象称为 冲突 。 把这种具有不同关键字值而具有相同哈希地址的对象称 “ 同义词 ” 。 在大多数情况下,冲突是不能完全避免的。这是因为所有可能的关键字的集合可能比较大,而对应的地址数则可能比较少。 对于哈希技术,主要研究两个问题: (1)如何设计哈希函数以使冲突尽可能少地发生。 (2)发生冲突后如何解决 。 二、哈希函数 构造好的 哈希函数 的方法,应能使冲突尽可能地少,因而应具有较好的随机性。这样可使一组关键字的散列地址均匀地分布在整个地址空间

哈希拉链法

不羁岁月 提交于 2020-02-18 08:25:07
前言 前面学习到的几种算法比如 红黑树 , 二叉搜索树 ,查找插入 时间复杂度 最快也只能到 O(logn) .现在介绍一种算法可以使查找插入 时间复杂度 达到常数级别。 散列表(Hash table) 也称为 哈希表 。是字典的一种抽象。比如说你要查一个字,通过这个字的拼音首字母,找到这个字的页码,然后翻到那页找就行了。这种方法直接把查找 时间复杂度 降到了常数。但是要牺牲一定的计算索引的时间。计算索引的那个函数称为 哈希函数 ( 散列函数``)。如果两个不同的 key`算出了同一个索引,此时就要用到一定的方法来解决哈希冲突。 哈希函数 哈希函数 一般具有如下特点。 相等的 key 产生相等的 哈希值 计算简单方便 哈希值 均匀分布。(若过度集中,则容易使效率降低到 o(n) ) 构造 哈希函数 有多种方法,这里不详细讲解。 哈希冲突 若两个不相等的 key 产生了相等的 哈希值 ,这时则需要采用 哈希冲突 。 拉链法 Java 标准库的 HashMap 基本上就是用 拉链法 实现的。 拉链法 的实现比较简单,将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。 实现步骤 得到一个 key 计算 key 的 hashValue 根据 hashValue 值定位到 data[hashValue] 。( data

collection(list,set,map)、HashMap

断了今生、忘了曾经 提交于 2020-02-18 02:53:39
collection里面有什么子类?(list和set是实现了collection接口的。)   List: 1.可以允许重复的对象(可重复,有序集合)。 2.可以插入多个null元素。 3.常用的实现类有 ArrayList、LinkedList 和 Vector。ArrayList 最为流行,它提供了使用索引的随意访问,而 LinkedList 则对于经常需要从 List 中添加或删除元素的场合更为合适。 ———————————————— Set: 1.不允许重复对象(不可重复,无序集合)。 2 只允许一个 null 元素 3.Set 接口最流行的几个实现类是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基于 HashMap 实现的 HashSet;TreeSet 还实现了 SortedSet 接口,因此 TreeSet 是一个根据其 compare() 和 compareTo() 的定义进行排序的有序集合。而且可以重复。 ———————————————— Map: 1.Map不是collection的子接口或者实现类。Map是一个接口。 2.不允许重复元素。 3. Map 里你可以拥有随意个 null 值但只能有一个 null (key)键。 4. Map 接口最流行的几个实现类是 HashMap、LinkedHashMap、Hashtable