[BS]散列表 哈希表 Hash table

《第五章》 散 列

散列表的实现常常叫做散列(hashing)。散列是一种用于以常数平均时间执行插入、删除和查找的技术。

关于散列有一个很重要的概念:散列函数。散列函数是散列的关键处之一,散列函数又是基于映射机制的一种对应关系(一般是多对一的关系)。

这章可以分为5个部分:一般想法,散列函数,分离链接法,开放定址法(可分为线性探测、平方探测、双散列)、再散列、可扩散列。

本文只写到前四节。即:一般想法,散列函数,分离链接法,开放定址法(可分为线性探测、平方探测、双散列)(

第五章第一节:一般想法

把散列表当做一个简单的数组(其实我们会知道,散列表的实质就是一个数组),将这个数组的大小记录为TableSize。这么一来,我们可以根据

数组对应的下标[ 0 , TableSize - 1 ]来为我们将要存入的元素分配存放位置。下图是一个简单的理想散列表:

YCX 2011716001被散列到了 1 ;

LeiLei 2011716037被散列到了 4 ;

Tracy 2011716049被散列到了 6;

这就是散列的基本思想。如果元素很多(超过了10个),并且不改变数组的大小,那么肯定有散列数是重复的吧?那么如何存放这些重复的元素呢?

这就是散列中最棘手的问题之一“collision”(译为冲突)。在研究如何解决冲突的过程下,产生了几种解决办法:分离链接法,开放定址法。

在介绍这几个冲突解决办法之前我们先看一下什么是散列函数。

第五章第二节:散列函数

设Hash( X )为散列函数,像这些:Hash( X ) = X % TableSize  或者 Hash( X ) = (将所有字符的ACSII码相加)

或更为复杂一点的 Hash( X ) = Key[ 0 ] + 27 * Key[ 1 ] + 729 * Key[ 2 ]。这几个函数依次将数组的“利用率”提高了。

第五章第三节:分离链接法

这节比较简单,与链表本质一样。(

第五章第三节:开放定地址法

分为 线性探测法、平方探测法,双散列。

与分离链接法的区别是:开放定地址法再产生冲突的时候采用的不是分离链接的机制,而是增加了一种我称之为探测函数的函数。你确定名字足够形象?()

线性探测法的探测函数(绿色的)是:

hi (
X ) = ( Hash( X ) + F( i ) ) % TableSize , F( i ) = i ; i=1,2,3,4... ,Hash( X ) = X % TableSize(散列函数)

探测函数是怎么发挥作用的呢?例如:我们要将关键字{ 89,18,49,58,69 }依次放入散列表,那么过程是这样的:

机制是这样的:在每个元素进入散列表之前,先调用散列函数( Hash( X ) = X % TableSize )来处理这个数,当遇到冲突的时候请探测函数前来解围。

89被送到Hash( X ),处理....Hash( 89 ) = 89 % 10 = 9;查看散列号9可用,所以将其放入9中,如图:

TableSize = 10
0  
1  
2  
3  
4  
5  
6  
7  
8  
9 89

18 被送到Hash( X ),处理....Hash( 18 ) = 18 % 10 = 8;查看散列号8可用,所以将其放入8中,如图:

0  
1  
2  
3  
4  
5  
6  
7  
8 18
9 89

49 被送到Hash( X ),处理....Hash( 49 ) = 49 % 10 = 9;查看散列号9不可用,所以请求探测君前来,[],放开那个数,让我来!!!

49 被送到探测函数中,处理....h1 (49
) = ( 9 + 1 ) % 10 = 0;查看散列号0,发现可用,49被送到了0处,如图:

0 49
1  
2  
3  
4  
5  
6  
7  
8 18
9 89

58被送到Hash( X ),处理....Hash( 58 ) = 58 % 10 = 8;查看散列号8不可用,所以请求探测君前来,[],放开那个数,让我来!!!

58 被送到探测函数中,处理....h1 (58
) = ( 8 +1 ) % 10 = 9;查看散列号9,发现不可用,探测君继续探测:

58 被送到探测函数中,处理....h2 (58
)= ( 8 +2 ) % 10 = 0;查看散列号0,发现不可用,探测君继续探测:

58 被送到探测函数中,处理....h3 (58
) = ( 8 +3 ) % 10 = 1;查看散列号1,发现可用,58几经辗转终于有了着落1处,如图:

0 49
1 58
2  
3  
4  
5  
6  
7  
8 18
9 89

69被....这个就不说了吧?如果一切正常的话那么如图所示:

0 49
1 58
2 69
3  
4  
5  
6  
7  
8 18
9 89

那么平方探测法呢?同理,除了F( i )不一样,其余的分析过程都是一样一样的。不再赘述。

时间: 2024-08-29 08:27:55

[BS]散列表 哈希表 Hash table的相关文章

PHP关联数组与哈希表(hash table) 不指定

PHP中有一种数据类型非常重要,它就是关联数组,又称为哈希表(hash table),是一种非常好用的数据结构. 在程序中,我们可能会遇到需要消重的问题,举一个最简单的模型: 有一份用户名列表,存储了 10000 个用户名,没有重复项: 还有一份黑名单列表,存储了 2000 个用户名,格式与用户名列表相同: 现在需要从用户名列表中删除处在黑名单里的用户名,要求用尽量快的时间处理. 这个问题是一个小规模的处理量,如果实际一点,2 个表都可能很大,比如有 2 亿条记录. 我最开始想到的方法,就是做一

哈希表(Hash table)(1)

哈希表(Hash table)经常被用来做字典(dictionary),或称符号表(symbol-table) 直接存取表(Direct-access table): ? 直接存取表(Direct-access table)的基本思想是:如果key的范围为0~m-1而且所有key都不相同, 那么可以设计一个数组T[0..m-1],让T[k]存放key为k的元素, 否则为空(NIL) ? 显然, 所有操作都是O(1)的 ? 问题:key的范围可能很大! 64位整数有18,446,744,073,7

哈希表 hash table

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. 给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数. 首先问题规模确定,例如5台服务器怎么把数据散落在5台上面呢,就用到了hash算法

什么叫哈希表(Hash Table)

散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. - 数据结构中,有个时间算法复杂度O(n)的概念来衡量某种算法在时间效率上的优劣.哈希表的理想算法复杂度为O(1),也就是说利用哈希表查找某个值,系统所使用的时间在理想情况下为定值,这就是它的优势.那么哈希表是如何做到这一点的呢? - 我们定义一个很大的有序数组,想要得到位于该数组第n个位置的值,它的算法复杂度

散列表(哈希表)

序言: 如果将一系列的记录按照关键字的某种函数存储,那么在查找某个数据的时候就可以直接通过关键字计算出来了,而不在需要“比较”,这样会非常高效,这就是散列技术. 所以散列技术就是:     存储位置=f(关键字)        不管是记录的存储还是查找,都用这种方法 散列技术具有很高的效率,但是使用起来有一些限制.如1个关键字对应多个记录的情况(比如在一个学校的学生中按性别查找,则对应太多的记录),此外散列技术同样不适合于范围查找和排序等操作. 一.散列函数的构造 在设计散了函数的时候主要考虑两

哈希表Hash

大家都学过数据结构: 内存里面为了更好的管理对象,通常采用链表或者数据以及Hash表来存储数据. 数据存储 一下是数据存储到计算机的两种模式 线性的存储:数组---寻址方便,更新不好(连续的) 链式的存储: 链表----寻址不方便,更新方便.(不连续的) 为了提高检索的速度,我们可以采取Hash机制,key采取数据存储,方便寻址,其次我们可以利用链表方便更新数据的具体的值. 哈希表Hash,布布扣,bubuko.com

散列表之直接寻址表

散列表之直接寻址表 直接寻址表的定义 直接寻址表的操作 直接寻址表的代码实现 dataNode的定义 直接寻址表的定义 测试文件 编译运行 总结 注意: 本文中的所有代码你可以在这里: https://github.com/qeesung/algorithm/tree/master/chapter11/11-1/directAddr(这里的会及时更新) 或者这里: http://download.csdn.net/detail/ii1245712564/8793509 找到 散列表之直接寻址表

(四)Redis哈希表Hash操作

Hash的全部操作如下: hset key field value # 将哈希表key中的字段field的值设为value hget key field # 返回哈希表key中的字段field的值value hmset key field1 value1 field2 value2 ... # 将多个field-value对设置到哈希表key中 hmget key field1 field2 ... # 返回哈希表key中字段field1,field2,...的值 hgetall key # 返

哈希表Hash:概念与基本操作

什么是Hash Hash就像是一个桶排,那只不过是把各个元素的数值当做下标进行存储.其最常用的用途就是用来判重.但是,如何对字符串进行判重,不可能一个一个往前超,若n上万则显然不可行.我们可以选择进行Hash,将每一个字符串或者大数字进行一定的操作即可进行. 对大整数类型进行Hash 取模法 对于每一个大整数进行取模,即除以一个大质数(例如107,10007,1000007,1-奇数个0-7),这样就作为数组的下标进行存储了. 为什么要对一个大整数取模 emmmmmm......经众多数学家证明