散列算法

哈希(散列) 学习笔记

耗尽温柔 提交于 2020-02-04 21:12:30
提示:本篇文章仅仅针对普及组的OIer,并且,这是网上少有的一篇关于介绍哈希代码的文章 注:提高组的大佬们勿喷。 文章目录 板子题 题目描述 输入 输出 样例输入 样例输出 提示 算法理解 哈希函数 哈希冲突 方法一:开放寻址法 方法二:挂链法 原题解析 板子题 题目描述 如题,给定 N N N 个字符串(第i个字符串长度为 M i M_i M i ​ ,字符串内包含数字、大小写字母,大小写敏感),请求出 N N N 个字符串中共有多少个不同的字符串。 输入 第一行包含一个整数 N N N ,为字符串的个数。 接下来 N N N 行每行包含一个字符串,为所提供的字符串。 输出 输出包含一行,包含一个整数,为不同的字符串个数。 样例输入 5 abc aaaa abc abcc 12345 样例输出 4 提示 时空限制: 1000 1000 1 0 0 0 ms, 128 M 128M 1 2 8 M 数据规模: 对于30%的数据: N < = 10 N<=10 N < = 1 0 , M i ≈ 6 M_i≈6 M i ​ ≈ 6 , M m a x < = 15 M_{max}<=15 M m a x ​ < = 1 5 ; 对于60%的数据: N < = 10000 N<=10000 N < = 1 0 0 0 0 , M i ≈ 100 Mi≈100 M i ≈ 1 0 0 ,

C#中Hashtable、Dictionary详解以及写入和读取对比

纵然是瞬间 提交于 2020-01-30 00:22:08
2013年04月22日 11:03 供稿中心: 互联网运营部 摘要: 在本文中将从基础角度讲解HashTable、Dictionary的构造和通过程序进行插入读取对比。 在本文中将从基础角度讲解HashTable、Dictionary的构造和通过程序进行插入读取对比。 一:HashTable 1.HashTable是一种散列表,他内部维护很多对Key-Value键值对,其还有一个类似索引的值叫做散列值(HashCode),它是根据GetHashCode方法对Key通过一定算法获取得到的,所有的查找操作定位操作都是基于散列值来实现找到对应的Key和Value值的。 2.我们需要使用一个算法让散列值对应HashTable的空间地址尽量不重复,这就是散列函数(GetHashCode)需要做的事。 3.当一个HashTable被占用一大半的时候我们通过计算散列值取得的地址值可能会重复指向同一地址,这就是哈希冲突。 在.Net中键值对在HashTable中的位置Position= (HashCode& 0x7FFFFFFF) % HashTable.Length,.net中是通过探测法解决哈希冲突的,当通过散列值取得的位置Postion以及被占用的时候,就会增加一个位移x值判断下一个位置Postion+x是否被占用,如果仍然被占用就继续往下位移x判断Position+2*x位置是否被占用

散列

百般思念 提交于 2020-01-28 21:43:03
什么是哈希表? 原文链接:https://blog.csdn.net/yyyljw/article/details/80903391 哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。 哈希表hashtable(key,value) 就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。(或者:把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。) 数组的特点是:寻址容易,插入和删除困难; 而链表的特点是:寻址困难,插入和删除容易。 那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表,哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法——拉链法

哈希表

与世无争的帅哥 提交于 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选的不好

JedisCluster配置集群api测试

你。 提交于 2020-01-26 20:30:54
项目中会常用到redis,但JedisCluster的使用api还是比较多,经常可能会记不太清楚,故这里将大部分JedisCluster的api贴出来,供大家参考。 一、redis在工作是一个常见的工具,这里对redis和springboot形成集群的使用。 (1)引入对应redis集群所需要maven文件 <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.0.5.RELEASE</version> </dependency> (2) 在配置文件配置 redis.properties 配置redis集群必要参数 #客户端超时时间单位是毫秒 默认是2000 redis.timeout=10000 #最大空闲数 redis.maxIdle=300 #连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal #redis

散列表(一).散列表基本内容介绍

耗尽温柔 提交于 2020-01-21 23:57:01
  一说到散列表,大家脑子想到的词就是:Hashmap、key-value、查找速度快、增删速度快等等。确实,在我们平常的学习生活中,散列表是很常见、也是用的很多的数据结构。那么散列表是怎样设计出来的,为什么它既可以和数组一样查询快,又可以和链表一样快增删,本节让我们一起了解一下什么是散列表、什么是散列函数、它究竟是如何设计出来的。 散列思想   什么是散列思想呢?散列表还有一个英文名叫做Hashtable,也叫做“哈希表”、“hash表”,hash我们都了解,是同过一定的算法、hash算法得到一个对象的散列值,用来标识对象本身的算法。   我们来举一个例子,假如有50个同学参加数学竞赛,为了能快速方便地找到每一个人,所以每个人都设立一个编号,从1到50,代表50个学生。现在如果我们用代码去实现这一功能的话,我们可以将这50个学生放到数组中去,从数组下标为1的位置开始,放入编号为1的学生,以此类推,将学生的编号和数组的下标一一对应,当我们要找第32个学生的时候,直接arr[32]就可以找到这个学生了,这样,就达成了O(1)的时间复杂度。实际上,这个例子已经用到了散列思想,能够快速地找到我们想找的学生,如果你觉得不够明显的话我们可以稍加改造一下。   假如,老师说编号这样太简单了,无法明显地表面这个学生的信息,需要再加上年级、班级这些信息,变成了6位数字,比如020433

常见基本数据结构——散列

你离开我真会死。 提交于 2020-01-17 23:48:21
散列表的实现通常叫做散列。散列是一种用于以常数平均时间执行插入、删除和查找的技术。但是任何排序的信息都不会得到有效的支持。所以FindMax(),FindMin(),以及以线性时间打印的操作都是散列所不支持的。 理想的散列表数据结构值不过是一个包含有关键字的具有固定大小的数组。 关键字映射的函数叫做散列函数,通常散列函数应该运算简单并且保证任何两个不同的关键字映射到不同的单元。不过这是不可能的,因为单元的数目是有限的,然而关键字是用不完的。因此,我们寻找一个散列函数,该函数要在单元之间均匀的分配的关键字。对于两个关键字映射到同一个值的时候,我们称之为冲突,需要设定一个函数来进行处理。 散列函数 对于关键字是整数,则一般合理的方法就是直接返回"Key mod TableSize"的结果,除非Key具有某些不理想的性质。例如:表的大小是10,但是关键字的大小都是0为个位。好的大小通常是保证表的大小是一个素数。 通常,关键字是字符串,在这种情况下,散列函数需要仔细的选择。 一种比较简单的方法是把字符串中的字符的ASCLL码值加起来。下面是这种方式的代码实现: Indexx Hash(const char *Key, int TableSize){ unsigned int HashVal = 0; while(*Key != '\0'){ HashVal += *Key++; }

散列

蹲街弑〆低调 提交于 2020-01-12 13:21:13
以下为学习笔记,来源于《数据结构与算法分析——C语言描述》 散列的插入、删除、查找时间为O(1),因为其不是像树一样通过比较来进行上面的操作,而是直接进行。 理想的散列表结构:一个包含有关键字的具有固定大小的数组。   表的大小记为TableSize,index从0到TableSize-1。 散列函数 (1)散列函数:每个关键字通过散列函数映射到0~TableSize-1这个范围的某个数,并且关键字被放到散列表适当的单元中。 (2)理想散列函数的要求:两个不同的关键字被映射到不同的单元;在TableSize大小的散列表里均匀地分配关键字。 (3)如果输入的关键字为整数,则一般合理的方法是返回“key mod TableSize”的结果;    通常,关键字是字符串,一种方法是把字符串中字符的ASCII码值加起来,再对TableSize求余。 冲突 (1)冲突:当一个元素插入散列表时,其插入的单元已经存在另一个元素时,就产生冲突,冲突需要消除。 (2)解决冲突的常用方法:分离链接法和开放定址法 分离链接法 其做法是将散列到同一个单元的所有元素保留到一个表中(即建立个链表保存这些冲突的元素),为了方便,这些表都有表头。 开放定址法 分离链接法缺点是需要指针,且给新单元分配地址需要时间,这使得算法的速度较慢。开放定址法,在发生冲突时尝试在原来的散列表里选择空的单元(而不是建新的空间)

数据结构学习笔记(0X08)--散列表

余生长醉 提交于 2020-01-07 08:29:50
一、散列表的由来? 1.散列表来源于数组,它借助散列函数对数组这种数据结构进行扩展,利用的是数组支持按照下标随机访问元素的特性。 2.需要存储在散列表中的数据我们称为键,将键转化为数组下标的方法称为散列函数,散列函数的计算结果称为散列值。 3.将数据存储在散列值对应的数组下标位置。 二、如何设计散列函数? 总结3点设计散列函数的基本要求 1.散列函数计算得到的散列值是一个非负整数。 2.若key1=key2,则hash(key1)=hash(key2) 3.若key≠key2,则hash(key1)≠hash(key2) 正是由于第3点要求,所以产生了几乎无法避免的散列冲突问题。 三、散列冲突的解放方法? 1.常用的散列冲突解决方法有2类:开放寻址法(open addressing)和链表法(chaining) 2.开放寻址法 ①核心思想:如果出现散列冲突,就重新探测一个空闲位置,将其插入。 ②线性探测法(Linear Probing): 插入数据:当我们往散列表中插入数据时,如果某个数据经过散列函数之后,存储的位置已经被占用了,我们就从当前位置开始,依次往后查找,看是否有空闲位置,直到找到为止。 查找数据:我们通过散列函数求出要查找元素的键值对应的散列值,然后比较数组中下标为散列值的元素和要查找的元素是否相等,若相等,则说明就是我们要查找的元素;否则,就顺序往后依次查找

学习笔记-java 集合

偶尔善良 提交于 2020-01-05 04:12:48
背景: 看的是《java核心技术 第8版》,覆盖jdk1.6。主要是对集合全局和细节进行全面掌握,较深入的理解集合。本人对java比较熟悉,但是对于细节的理解不深,知识点还不全,这是知识的查缺不漏。 一.集合接口 接口和实现分离 当程序中使用集合时,一旦构建了集合就不需要知道究竟使用的哪种实现,因此,只有构建集合对象时,使用具体的类才有意义。可以使用接口类型存放集合的引用。 2. 集合接口和迭代接口 java迭代器应该认为是位于两个元素中间,当调用next时,迭代器就越过下一个元素。 Iterator接口的remove方法会删除上次调用next方法时返回的元素。重要的是,对next方法和remove方法的调用具有互相依赖性。 为了能够让实现者更容易得实现这个接口,java类库提供了一个类AbstractCollection。 二.具体的集合 1.链表 linkedlist Linkedlist和Arraylist区别:从实现上,al采用的是数组,可以高效地随机访问;而ll采用的是内部了entry,这个类里有对象还有节点的前后指针,因此不能随机访问,只能从头遍历,但是插入,删除简单,不需要移动前后数据。 Linkedlist.add方法将对象添加到链表的尾部;而经常需要在链表的中间插入元素,而接口Iterator中没有add方法,集合类提供了子接口Listiterator