哈希表

哈希表

与世无争的帅哥 提交于 2020-01-28 13:41:46
1.哈希表的定义 哈希表:根据关键码值(key value)直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找速度,这个映射函数叫做哈希函数,存放记录的数组叫做哈希表。 给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。 举例:新华字典,我想要获取“按”字详细信息,去根据拼音an去查找拼音索引,首先去查an在字典的位置,得到“安”,这个过程就是键码映射。在公式里,就是通过key去查找f(key)。其中,按就是关键字(key),f(key)就是字典索引,也就是哈希函数,查到的页码4就是哈希值。 2.如何构造哈希表 根据设定的哈希函数f=H(key)和处理冲突的方法,将一组关键字映像到一个有限的连续的地址集上,并以关键字在地址集中的”象”作为记录在表中的存储位置,这一映像过程,称为构造哈希表(散列表)。 几种常见的哈希函数(散列函数)构造方法 直接定址法 取关键字或关键字的某个线性函数值为散列地址。 即 H(key) = key 或 H(key) = a*key + b,其中a和b为常数。 比如 除留余数法 取关键字被某个不大于散列表长度 m 的数 p 求余,得到的作为散列地址。对除数p的选择很重要,若p选的不好

Lua性能优化技巧[三 关于表]

本秂侑毒 提交于 2020-01-28 00:27:18
原作者 Roberto Ierusalimschy 翻译 hillin 翻译版权所有©2011 hillinworks,转载需征得译者允许。 目录 一 前言 二 基本事实 三 关于表 四 关于字符串 五 削减、重用与回收 六 最后的提示 一般情况下,你不需要知道Lua实现表的细节,就可以使用它。实际上,Lua花了很多功夫来隐藏内部的实现细节。但是,实现细节揭示了表操作的性能开销情况。因此,要优化使用表的程序(这里特指Lua程序),了解一些表的实现细节是很有好处的。 Lua的表的实现使用了一些很聪明的算法。每个Lua表的内部包含两个部分:数组部分和哈希部分。数组部分以从1到一个特定的n之间的整数作为键来保存元素(我们稍后即将讨论这个n是如何计算出来的)。所有其他元素(包括在上述范围之外的整数键)都被存放在哈希部分里。 正如其名,哈希部分使用哈希算法来保存和查找键。它使用被称为开放地址表的实现方式,意思是说所有的元素都保存在哈希数组中。用一个哈希函数来获取一个键对应的索引;如果存在冲突的话(意即,如果两个键产生了同一个哈希值),这些键将会被放入一个链表,其中每个元素对应一个数组项。当Lua需要向表中添加一个新的键,但哈希数组已满时,Lua将会重新哈希。重新哈希的第一步是决定新的数组部分和哈希部分的大小。因此,Lua遍历所有的元素,计数并对其进行归类,然后为数组部分选择一个大小

哈希表

南笙酒味 提交于 2020-01-27 07:30:50
一.符号表问题 1.一个表里面放着n条记录,(记录x:x通常是一个指向实际数据的指针) 2.在每个记录中,存在一个记录的键,还存在一些卫星数据(属于键的附加数据) 3.排序是对记录进行排序,而不是关键字 4.对表进行操作:添加记录,删除记录,查找具有特定键的记录 二.直接映射表(数组) 1.适用于关键字的全域(可能存储的关键字)较小的情况 2.数组的每个位置对应全域中的一个关键字,关键字k的元素被存放在槽k中 3.缺陷:如果关键字只有几千,而关键字的全域需64位来表示,导致大量空槽 1 class direct_address_table: 2 '''直接寻址表''' 3 def __init__(self, T=[], size=0): 4 if len(T) == 0: 5 self.T = [None for i in range(size)] 6 else: 7 self.T = T 8 self.size = size 9 '''对于节点''' 10 def search(self, k): 11 return self.T[k] 12 13 def insert(self, x): 14 self.T[x.key] = x 15 16 def delete(self, x): 17 self.T[x.key] = None 18 19 class Node: 20

HashMap简介

女生的网名这么多〃 提交于 2020-01-26 21:10:33
HashMap简介 在Java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。 适用场景:读多写少,(读取多插入少) 一般场景 --》 一次写入,剩下全读。 读取速度最快的,是根据下标读数组,时间复杂度O(1) ,但是插入速度慢。 大概结构上个图: 但实际的结构构造要比这复杂的多,涉及到红黑树结构。(找了个大概的图,先了解下。) 接下来复习下几种基础结构: 数组 :采用一段连续的存储单元来存储数据。对于指定下标的查找,时间复杂度为O(1);通过给定值进行查找,需要遍历数组,逐一比对给定关键字和数组元素,时间复杂度为O(n),当然,对于有序数组,则可采用二分查找,插值查找,斐波那契查找等方式,可将查找复杂度提高为O(logn);对于一般的插入删除操作,涉及到数组元素的移动,其平均复杂度也为O(n) 数组优缺点总结 优点: 1、按照索引查询元素速度快 2、能存储大量数据 3、按照索引遍历数组方便 缺点: 1、根据内容查找元素速度慢 2、数组的大小一经确定不能改变。 3、数组只能存储一种类型的数据 4、增加、删除元素效率慢 5、未封装任何方法,所有操作都需要用户自己定义。 线性链表 :对于链表的新增,删除等操作

《数学之美》-----读后感

邮差的信 提交于 2020-01-26 15:58:37
《数学之美》-----读后感 1.如何衡量分词效果的好坏? 2.如何构建网络爬虫? 3.影响搜索引擎的因素 4.余弦相似度在自然语言处理中的应用 5.如何判断两个集合是否相同? 6.密码 7.解决噪音干扰(反作弊)的基本思路 8.如何衡量搜索结果的权威性? 9.数学模型的重要性 10.拼音输入法 11.哈希表的存储效率一般不超过50%? 后记 参考链接 一直以来都不喜欢看书,比较偏爱数学,觉得只要知道思路不用记太多长篇大论的东西。本科学了四年的数学与应用数学,我从不怀疑数学的价值,但是天天面对复杂的定理和证明,一度时间让我很怀疑数学的实用性,毕竟很多人并不需要知道每一步是怎末推导的,只需要把对应的公式记住就完事了。 大三决心考研的时候,便当了逃兵,转到了统计,考研复试是我第一次感受到本科四年的数学知识在我身上的实际体现,复试笔试的题目好多都是本科只有数学专业才学的特别难的概率论和数理统计的课后习题,庆幸自己没有偷懒,所有的习题都自己做了一遍。随着接触的统计和自然语言处理的知识越来越多,我越来越感受到数学的实用性,那些复杂的推导和证明可以在实际中更快更清晰的解决更多问题。 在朋友和老师的推荐下,便读了吴军老师的数学之美,更是加深了我对数学的认知,真正感受到了从统计学到天文学,数学不仅无处不在,而且无法替代。本文主要整理数学之美里面一些比较实际的问题,作为自己读书后的总结。 1

几分钟看完的javaSE基础(三)

为君一笑 提交于 2020-01-26 10:49:19
object 类 object是类层次结构的根类,每个类都使用Object作为超类。 String:概念-->多个字符串组成的字符序列,理解为字符数组; String 的跟 StringBuilder 和 StringBuffer 的区别在于String每次操作都会生成新的String对象,然后将指针指向新的String对象,而StringBuffer和StringBuilder可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下,最好不要使用Sting。 StringBuffer和StringBuilder的区别在于StringBuffer是线程安全的,而StringBuilder是非线程安全的。但是StringBuilder却比StringBuffer的性能高,所以在单线程的情况下建议使用StringBuilder,多线程的情况下建议使用StringBuffer. 正则: 正则表达式由两种基本字符组成 原义字符:字符本身即是一个正则\t \n \r \f 元字符:* + ? $ ^ () [ ] {} ... 对正则表达式进行分类:字符类:[ abc] 可以出现abc中的任何一个进行匹配。[^abc] 对不是abc的字符进行匹配 范围类:[a-z] 表示代表a-z中的一个字符表示所有的小写英文 ----- >表示大小写的英文和数字[a-zA-Z0-9] 预定义类:

漫画 | 什么是散列表(哈希表)?

梦想的初衷 提交于 2020-01-24 19:58:58
创建与输入数组相等长度的新数组,作为直接寻址表。两数之和的期望是Target,将Target依次减输入数组的元素,得到的值和直接寻址表比较,如果寻址表存在这个值则返回;如果不存在这个值则将输入数组中的元素插入寻址表,再进行输入数组中的下一个元素。 再进一步优化可以将输入数组直接作为直接寻址表,控制对应的下标就好,代码如下: Code:直接寻址表 class Solution { public int[] twoSum(int[] nums, int target) { for (int i = 1; i < nums.length; i++) { int temp = target - nums[i]; for (int j = 0; j < i; j++) { if (temp == nums[j]) return new int[]{j, i}; } } return null; } } 动画:直接寻址表 数组里面每一个槽位放的是8个字节,用于一个指向外部类的引用。这个外部类可以是链表对象,也可以是红黑树对象,都可以存一个或者一个以上的元素,也可以是空链表或空树。散列表在某种意义上需要的数组空间可以比直接寻址表要少的很多。 散列函数是将所有元素的键转换为自然数,自然数的数集是{0,1,2,……}。 如果所有元素的键是正整数,最常用的方法是求模(除留余数法)

leetcode刷题(37)——141. 环形链表

送分小仙女□ 提交于 2020-01-24 18:36:54
给定一个链表,判断链表中是否有环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。 示例 1: 输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。 示例 2: 输入:head = [1,2], pos = 0 输出:true 解释:链表中有一个环,其尾部连接到第一个节点。 示例 3: 输入:head = [1], pos = -1 输出:false 解释:链表中没有环。 这题也有两种解法: 方法一:哈希表 思路 我们可以通过检查一个结点此前是否被访问过来判断链表是否为环形链表。常用的方法是使用哈希表。 算法 我们遍历所有结点并在哈希表中存储每个结点的引用(或内存地址)。如果当前结点为空结点 null(即已检测到链表尾部的下一个结点),那么我们已经遍历完整个链表,并且该链表不是环形链表。如果当前结点的引用已经存在于哈希表中,那么返回 true(即该链表为环形链表)。 public boolean hasCycle(ListNode head) { Set<ListNode> nodesSeen = new HashSet<>(); while (head != null) { if (nodesSeen

数据结构与算法之哈希表

…衆ロ難τιáo~ 提交于 2020-01-24 15:59:16
哈希表 google公司的一个上机题: 有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,名字,住址…),当输入该员工的id时,要求查找到该员工的 所有信息. 要求: 不使用数据库,速度越快越好=>哈希表(散列) 添加时,保证按照id从低到高插入 (实际上就是叫我们创建链表数组) 代码实现 package hashtab ; import java . util . Scanner ; public class HashTabDemo { public static void main ( String [ ] args ) { // 创建哈希表 HashTab hashTab = new HashTab ( 7 ) ; // 写一个简单菜单 String key = "" ; Scanner scanner = new Scanner ( System . in ) ; while ( true ) { System . out . println ( "add: 添加雇员" ) ; System . out . println ( "list: 显示雇员" ) ; System . out . println ( "find: 查找雇员" ) ; System . out . println ( "del: 删除雇员" ) ; System . out

异或算法

橙三吉。 提交于 2020-01-24 02:49:00
最近碰到很多通过巧妙着运用 位运算 来巧妙解决复杂问题的算法,今天分享的这道题,或许能够开拓你的一些算法思维。 题目描述 有一组存放 ID 的数据。并且 ID 取值为 0 - (N-1) 之间,其中只有一个 ID 出现的次数为 1,其他的 ID 出现的次数都等于 2,问如何找到这个次数为 1 的 ID ? 解法一:巧用数组下标 不知道有多少人还记得我之前分享的 巧用数组下标 的技巧: 一些常用的算法技巧总结 。 我的第一想法便是采用 下标法 来解决,把 ID 作为数组 arr 的下标,在遍历 ID 的过程中,用数组记下每个 ID 出现的次数,即每次遍历到 ID = n,则 arr[n]++。 之后我们在遍历数组 arr,找到 arr[n] = 1 的ID,该下标 n 便是我们要寻找的目的 ID。 这种方法的时间复杂度为 O(N),空间复杂度为 O(N)。 解法二:巧用哈希表 显然时间复杂度是无法再降低的了,因为我们必须要遍历所有的 ID,所以时间复杂度最少都得为 O(N)了,所以我们要想办法降低空间复杂度。 大家想一个问题,假如我们检测到某个 ID 已经出现了 2 次了,那么这个 ID 的数据我们还需要存储记录吗?大部分的 ID 都出现了 2 次,这一大部分的数据真的需要存储吗? 答是不用的,因为出现 2 次的 ID 不是我们所要找的。所以我们可以优化 解法一 ,我们可以采用