文章目录
数据结构-PHP 哈希表(Hash Table)的实现
这篇文章主要介绍一下哈希表(Hash Table)
的实现原理,哈希表(Hash Table) 也叫散列表
,它通过把关键码值(key-value)映射到表中一个位置来访问,以加快其查找的速度。这个映射函数叫做哈希函数
,存放记录的数组叫哈希表(Hash Table)
。
1.哈希表(Hash Table)的特点
- 访问速度很快,将指定的 Key 都映射到一个地址上,在访问时,可以直接跳到那个地址。
- 空间换时间,哈希表充分体现了空间换时间的思想。
- 无序,哈希表是无序的。它为了能快速访问元素,值是根据哈希函数直接找到存储地址的。
- 可能会产生哈希冲突,不同的值通过哈希函数可能存在相同值的情况,这时就需要采用冲突解决方案。
2.哈希函数的原理
下面举几个简单的 哈希函数
实现原理,主要说明如何将不同类型的值转化为一个小整数(小整数可以在数组中表示索引,即表示地址):
2.1 大整数转化为小整数(数组索引)
一个最简单的办法是 模(mod)
一个 素数
:
Tips:从图中可以看出,不同的数对一个
素数
模值区分度比较高,分布更加均匀。
下面是有人研究好的一个列表,其中 lwr
表示你取值范围的下界,upr
表示你取值范围的上界,prime
表示该范围的值对该值求模
区分度最好:
2.2 浮点型转化为小整数(数组索引)
可以先将浮点型扩大倍数转化为整型,然后按照大整数的方式处理即可。
2.3 字符串
十进制表示数字: 166 = 1 * 10^2 + 6 * 10^1 + 6 * 10^0
二十六进制表示字母: code = c * 26^3 + o * 26^2 + d * 26^1 + e * 26^0
hash(code) = (c * B^3 + o * B^2 + d * B^1 + e * B^0) % M
hash(code) = ((((c * B) + o) * B + d) * B + e) % M
Tips:其中
B
表示进制,M
表示一个合适的素数
。
2.4 用 PHP 代码实现的 HashCode 类
下面这个类可以实现输入一个字符串,然后返回一个正整数的哈希值:
<?php
trait HashCode
{
function hashCode64($str) {
$str = (string)$str;
$hash = 0;
$len = strlen($str);
if ($len == 0 )
return $hash;
for ($i = 0; $i < $len; $i++) {
$h = $hash << 5;
$h -= $hash;
$h += ord($str[$i]);
$hash = $h;
$hash &= 0x7FFFFFFF;
}
return $hash;
}
}
Tips:这里简单封装成
trait HashCode
方便其他类调用,其中$hash &= 0x7FFFFFFF
的意思是将输出值最高位符号位保证为0,表示正数输出。
3. 定义一个带有哈希函数的 Student 类
为了方便对哈希值的理解,下面定义一个学生类(Student)
,该类中包含 年级(grade)
、班级(class)
、姓氏(firstName)
、名字(lastName)
:
<?php
class Student
{
use HashCode;
//学生年级
public $grade = null;
//班级
public $class = null;
//姓氏
public $firstName = null;
//名字
public $lastName = null;
public function __construct($grade, $class, $firstName, $lastName)
{
$this->g