哈希函数

常见快速搜索算法图解

喜夏-厌秋 提交于 2020-01-29 11:03:51
搜索 搜索是在一个项目集合中找到一个特定项目的算法过程。搜索通常的答案是真的或假的,因为该项目是否存在。搜索的几种常见方法:顺序查找、二分法查找、二叉树查找、哈希查找 二分查找 二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。 二分查找的实现 (非递归实现) def binary_search_2 ( alist , item ) : """二分查找:while版""" n = len ( alist ) first = 0 last = n - 1 while first <= last : mid = ( first + last ) // 2 if alist [ mid ] == item : return True elif item < alist [ mid ] : last = mid - 1 else : first = mid + 1

哈希表

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

散列表

匆匆过客 提交于 2020-01-22 00:14:23
散列表 又叫 哈希表 (hash table)。 通过访问key而直接访问存储的value值 。它的key - value之间存在一个映射函数,我们可以通过key值和“看不到”的 映射函数 (散列函数)访问对应的value值。这加快了查找的速度!存放记录的数组称做 散列表。散列方法不同于顺序查找、二分查找、二叉排序树及B-树上的查找。它不以关键字的比较为基本操作, 采用直接寻址技术 (就是说,它是直接通过key 映射[映射函数,实现的方式有多种] 到内存地址上去的) 。在理想情况下,无须任何比较就可以找到待查关键字,查找的期望时间为O(1)(面试的时候犯了这个错误)。 举个形象的例子来说:为了查找电话簿中某人的号码,可以创建一个按照人名首字母顺序排列的表(即建立人名 到首字母 的一个 函数 关系),在首字母为W的表中查找“王”姓的电话号码,显然比直接查找就要快得多。这里使用人名作为 关键字 ,“取首字母”是这个例子中 散列函数 的函数法则 ,存放首字母的表对应 散列表 。关键字和函数法则理论上可以任意确定。[维基百科] 散列表  设所有可能出现的关键字集合记为U(简称全集)。实际发生(即实际存储)的关键字集合记为K(|K|比|U|小得多)。  散列方法是使用函数h将U映射到表T[0..m-1]的下标上(m=O(|U|))。这样以U中关键字为自变量

【数据结构与算法】HashTable相关操作实现 -- 基于Java的实现

会有一股神秘感。 提交于 2020-01-22 00:09:58
哈希表 哈希表又叫散列表,是实现字典操作的一种有效数据结构。哈希表的查询效率极高,在理想情况下,查找一个元素的平均时间为O(1)。 哈希表就是描述key—value对的映射问题的数据结构,即在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字与哈希表中唯一一个存储位置相对应。我们称这个对应关系f为哈希函数,这个存储结构即为哈希表。 直接寻 址表 当关键字的全域U比较小时,直接寻址是一种简单而有效的技术,它的哈希函数很简单:f(key) = key,即关键字大小直接与元素所在的位置序号相等。另外,如果关键字不是自然数,我们需要通过某种手段将其转换为自然数,比如可以将字符关键字转化为其在字母表中的序号作为关键字。直接寻址法不会出现两个关键字对应到同一个地址的情况,既不会出现f(key1) = f(key2)的情况,因此不用处理冲突,这便是其优点所在。 散列表 直接寻址的缺点非常明显,如果全域U很大,则在一台标准的计算机可用内存容量中,要存储大小为U的一张表也许不太实际,而且,实际需要存储的关键字集合K可能相对U来说很小,这时散列表需要的存储空间要比直接表少很多。散列表通过散列函数f计算出关键字key在槽的位置。散列函数f将关键字域U映射到散列表T[0...m-1]的槽位上。但是这里会存在一个问题:若干个关键字可能映射到了表的同一个位置处(算法导论上名其曰“槽”)

查找三 哈希表的查找

馋奶兔 提交于 2020-01-16 10:45:59
目录 要点 哈希表和哈希函数 在记录的存储位置和它的关键字之间是建立一个确定的对应关系(映射函数),使每个关键字和一个存储位置能 唯一对应 。这个映射函数称为 哈希函数 ,根据这个原则建立的表称为 哈希表(Hash Table) ,也叫 散列表 。 以上描述,如果通过数学形式来描述就是: 若查找关键字为 key ,则其值存放在 f(key) 的存储位置上。由此, 不需比较便可直接取得所查记录 。 注:哈希查找与线性表查找和树表查找最大的区别在于,不用数值比较。 冲突 若 key1 ≠ key2 ,而 f(key1) = f(key2),这种情况称为 冲突 (Collision)。 根据哈希函数f(key)和处理冲突的方法将一组关键字映射到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“像”作为记录在表中的存储位置,这一映射过程称为 构造哈希表 。 构造哈希表这个场景就像汽车找停车位,如果车位被人占了,只能找空的地方停。 构造哈希表 由以上内容可知,哈希查找本身其实不费吹灰之力,问题的关键在于如何构造哈希表和处理冲突。 常见的构造哈希表的方法有 5 种: (1)直接定址法 说白了,就是小学时学过的 一元一次方程 。 即 f(key) = a * key + b。其中,a和b 是常数。 (2)数字分析法 假设关键字是R进制数(如十进制)。并且哈希表中

数据结构之哈希、哈希函数、哈希表

被刻印的时光 ゝ 提交于 2020-01-16 01:46:36
什么是哈希? 哈希,也称散列。在某种程度上,散列是与排序相反的一种操作,排序是将集合中的元素按照某种方式比如大小顺序排列在一起,而散列通过计算哈希值,打破元素之间原有的关系,使集合中的元素按照散列函数的分类进行排列。 为什么用哈希? 我们通常使用数组或者链表来存储元素,一旦存储的内容数量特别多,需要占用很大的空间,而且在查找某个元素是否存在的过程中,数组和链表都需要挨个循环比较,而通过 哈希 计算,可以大大减少比较次数。下面举个例子! 现在有 4 个数 {2,5,9,13},需要查找 13 是否存在。 1.使用数组存储,需要新建个数组 new int[]{2,5,9,13},然后需要写个循环遍历查找,这样需要遍历 4 次才能找到,时间复杂度为 O(n)。 2.而假如存储时先使用哈希函数进行计算,这里我随便用个函数: H[key] = key % 3; 四个数 {2,5,9,13} 对应的哈希值为: H[2] = 2 % 3 = 2; H[5] = 5 % 3 = 2; H[9] = 9 % 3 = 0; H[13] = 13 % 3 = 1; 然后把它们存储到对应的位置。 当要查找 13 时,只要先使用哈希函数计算它的位置,然后去那个位置查看是否存在就好了,本例中只需查找一次,时间复杂度为 O(1)。 因此可以发现,哈希 其实是随机存储的一种优化,先进行分类

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

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

java 复习之哈希表

梦想与她 提交于 2020-01-01 04:51:07
1.哈希定义 哈希表通过记录关键字为自变量的函数(称为哈希函数)得到访记录的存储地址查找,所以在哈希表中进行查找操作时,须用同一哈希函数计算得到待查询记录的存储地址,然后到相应的存储单元去获得相关信息再判定查找是否成功。 根据设计哈希函数H(key)和处理冲突的方法,将一组关键字映射到一个有限连限的地址集(区间)上,并以关键字在地址集中的“像”为记录在表中的存储位置,这种表称为哈希表,这一映射过程为哈希造表或散列,所得的存储位置称为哈希地址或散列地址。 冲突定义:对于某个哈希函数H(K)和两个关键字K1和K2,如果K1<>K2,而H(K1)=H(K2),则称为冲突。具有相同哈希函数值的关键字对该哈希函数来说称为同义词。 一般情况,冲突只能尽可能减少而不能完全避免,因为哈希函数是从关键字集合到地址集合映像。通常关键集合比较大,它的元素包含所有可能的关键字,而地址集合的元素仅为哈希表中的地址值。 对于哈希表,主要考虑两个问题:一是如何构造哈希函数,二是如何解决冲突。 2.哈希构造函数 Hash构造即为关键字与哈希地址映射关系建立。 构造哈希函数的原则是:①函数本身便于计算;②计算出来的地址分布均匀,即对任一关键字k,f(k) 对应不同地址的概率相等,目的是尽可能减少冲突。 哈希函数的构造方法很多,常用的有 直接定址法、数字分析法、平方取中法、折叠法、除留余数法、随机数法 等。 3

图解数据结构(04) -- 哈希表

左心房为你撑大大i 提交于 2019-12-30 23:08:15
哈希表 1、什么是哈希表 2、哈希函数 哈希函数的实现 3、哈希表的读写操作 写操作(put) 读操作(get) 扩容(resize) 4、总结 1、什么是哈希表 哈希表(hash table),这种数据结构提供了键(Key)和值 (Value)的映射关系;只要给出一个Key,就可以高效查找到它所匹配的Value,时间复杂度接近于O(1) 2、哈希函数 散列表在本质上也是一个数组,可是数组只能根据下标,像a[0]、a[1]、a[2]、a[3]、a[4]这样来访问,而散列表的Key则是以字符串类型为主的,例如以学生的学号作为Key,输入002123,查询到李四;或者以单词为Key,输入by,查询到数字46……所以需要一个“中转站”,通过某种方式, 把Key和数组下标进行转换,这个中转站就叫作哈希函数。 哈希函数的实现 以Java的常用集合HashMap为例,来讲解哈希函数在Java中的实现: 在Java及大多数面向对象的语言中,每一个对象都有属于自己的hashcode,这个hashcode是区分不同对象的重要标识,无论对象自身的类型是什么,它们的 hashcode都是一个整型变量。 既然都是整型变量,想要转化成数组的下标简单的转化方式就是按照数组长度进行 取模运算 index = HashCode (Key) % Array.length 通过哈希函数*

如何正确对用户密码进行加密?转自https://blog.csdn.net/zhouyan8603/article/details/80473083

时间秒杀一切 提交于 2019-12-23 04:27:12
本文介绍了对密码哈希加密的基础知识,以及什么是正确的加密方式。还介绍了常见的密码破解方法,给出了如何避免密码被破解的思路。相信读者阅读本文后,就会对密码的加密有一个正确的认识,并对密码正确进行加密措施。 作为一名Web开发人员,我们经常需要与用户的帐号系统打交道,而这其中最大的挑战就是如何保护用户的密码。经常会看到用户账户数据库频繁被黑,所以我们必须采取一些措施来保护用户密码,以免导致不必要的数据泄露。 保护密码的最好办法是使用加盐密码哈希( salted password hashing)。 重要警告: 请放弃编写自己的密码哈希加密代码的念头 !因为这件事太容易搞砸了。就算你在大学学过密码学的知识,也应该遵循这个警告。所有人都要谨记这点:不要自己写哈希加密算法! 存储密码的相关问题已经有了成熟的解决方案,就是使用 phpass ,或者在 defuse/password-hashing 或 libsodium 上的 PHP 、 C# 、 Java 和 Ruby 的实现。在对密码进行哈希加密的问题上,人们有很多争论和误解,可能是由于网络上有大量错误信息的原因吧。对密码哈希加密是一件很简单的事,但很多人都犯了错。本文将会重点分享如何进行正确加密用户密码。 密码哈希是什么? hash("hello") =