一、哈希表概念
哈希表(Hash Table):也叫散列表。是根据关键码值(Key Value)直接进行访问的数据结构。
哈希表通过(键 key )和(映射函数 Hash(key) )计算出对应的(值 value),把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做(哈希函数(散列函数)),存放记录的数组叫做(哈希表(散列表))。
二、哈希表的操作
关于哈希表,有两种操作:建立和查询
1.向哈希表中插入一个关键码值
将键(key)通过哈希函数转化为 值(value)并存放在哈希表中
2. 在哈希表中搜索一个关键码值
使用相同的哈希函数转化为 值(value)再在哈希表中查询
当处理数据为整型时,键(key)的大小通常为元素大小,再进行映射函数计算值,大致原理如下
三、哈希函数
概念:将哈希表中元素的键值映射为元素存储位置(值)的函数
哈希函数一般要满足以下条件:
① 易于计算,并且计算出来的值分布均匀(避免出现过多的哈希冲突)
② 哈希函数计算出的哈希值是一个固定长度的输出值
③ 一个键值不能对应两个hash值对应:
如果Hash(key1)!=Hash(key2) 那么key1与key2一定不相等
④一个hash值可以对应多个键值(哈希冲突)
四、哈希函数的方法
1. 直接定址法
取关键字本身 / 关键字的某个线性函数值作为哈希地址。
hash(key)= key 或者 hash(key)= a * key + b
2.除留余数法
假设哈希表的表长为 m ,取一个不大于 m 但接近或等于 m 的质数 p ,利用取模运算,将关键值转化为哈希地址(取质数可以尽量避免冲突)
hash(key)= key % p
3.平方取中法
先通过关键值平方的方式扩大相近数之间的差别,然后根据长度取关键值平方值的中间几位数作为哈希地址
hash(key)= ( key * key )/ 100 % 1000 // 先计算平方,去除末尾两位数,再取最后三位数(即取中间三位数作为哈希地址)
4.基数转换法
将关键字看成另一种进制的数再转化为原来进制的数,选其中几位作为哈希地址
五、哈希冲突
不同的关键字通过同一个哈希函数可能得到同一哈希地址,即 key1!=key2 而 hash(key1)== hash(key2)
当出现哈希冲突时,才用以下两种方法解决哈希冲突
1.开放地址法
将哈希表中的(空地址)向处理冲突开放,当哈希表未满时,处理冲突时需要尝试另外的单元,直到找到空的单元为止
发生冲突时,开放地址法按照下面方法求得新的哈希地址:H(i)= (hash(key)+ F (i) ) % m
如果H(1) 仍发生哈希冲突,则再一次通过上述操作处理出 H (2) ……直至 H (x) 不出现冲突
关于F(x)的计算:
①线性探测法:即 F(i)=i
②二次探测法:F(i)=1^2, -1^2, 2^2, -2^2……i^2,-i^2
③伪随机数序列:F(i)=rand()
2.链地址法
将具有相同哈希地址的元素(或记录)存储在同一个线性链表中
思想:将键值通过哈希函数得到的值存储入哈希表中,当出现哈希冲突时,采用链表的方法储存相同哈希值对应的键值。
1.每次插入键值时,最好插入表头(时间复杂度最低)
2.查询关键值时,通过哈希函数计算出对应的哈希地址 i ,然后在对应的链表上扫描一遍即可