[李景山php] 深入理解PHP内核[读书笔记]--第三章:变量及数据类型--变量的结构和类型--HashTable-1

来源:互联网 发布:航天远景软件 编辑:程序博客网 时间:2024/05/22 16:48

哈希表(Hash Table)


PHP用的最多的是字符串及数组,PHP容易上手也得益于灵活的数组类型。
哈希表通常提供查找(Search),插入(Insert),删除(Delete)等操作,通常哈希表的这些操作时间复杂度为O(1)。

基本概念


哈希表是一种通过哈希函数,将特定的键映射到特定的值的一种数据结构,它维护键和值之间一一对应关系。

键(key):用于操作数据的表示,例如PHP数组中的索引,或者字符串键等等。
槽(slot/bucket):哈希表中用于保存数据的一个单元,也就是数据真正存放的容器。
哈希函数(hash function):将key映射(map)到数据应该存放的slot所在位置的函数。
哈希冲突(hash collision):哈希函数将两个不同的key映射到同一个索引的情况。

哈希表可以理解为数组的扩展或者关联数组,数组用数字下标来寻址,如果关键字(key)的范围较小且是数字的话,我们可以直接使用数组来完成哈希表,而如果关键字范围太大,如果直接使用数组我们需要为所有可能的key申请空间。

很多情况会出现这样的情况:
空间足够,就会出现空间利用率比较低。

通过合理设计的哈希函数,我们就能将key映射到合适的范围,如果不同的key指向同一个value的时候,就会出现哈希冲突。

目前解决hash冲突的方法主要两种:链接法和开放寻址法。

冲突解决(hash 冲突解决)


连接法

连接法通过使用一个链表来保存slot值的方式来解决冲突,也就是当不同的key映射到一个槽中的时候用链表来保存这些值。所以使用连接法是在最坏的情况下,也就是所有的key都映射到同一个槽中了,这样哈希表就退化成了一个链表,这样的话操作链表的时间复杂度则成了O(n),这样哈希表的性能优势就没有了,所以选择一个合适的哈希函数是最为关键的。

如果哈希表退化成为连表,造成性能极具下降。

哈希冲突攻击利用的哈希表最根本的弱点是:开源算法和哈希实现的确定性以及可预测性,这样攻击者可以利用特殊构造的key来进行攻击。要解决这个问题的方法则是让攻击者无法轻易构造能够进行攻击的key序列。

总结:漏洞的原因就是攻击者知道出牌规则。
延伸:如果这样的话,攻击者可以通过构造一定的数组数据,造成链表性能瘫痪。

PHP的防止方法:限制用户提交数据字段数量。
但是攻击者可以使用 json_decode()进行攻击。

开放寻址法

开放寻址法:使用开放寻址法是槽本身直接存放数据,在插入数据时如果key所映射到的索引已经有数据了,这说明发生了冲突,这是会寻找一下槽,如果该槽也被占用了则继续寻找下一个槽,直接寻找到没有被占用的槽,在查找时也使用同样的策略来进行。

但是这样会出现新的问题:就是后续插入的数据需要更多此的查找新的位置,导致性能下降。

装载因子是哈希表保存的元素数量和哈希表容量的比,开放寻址最好不要大于0.5

哈希表的实现


实现哈希表的主要需要完成三个问题:
1 实现哈希函数
2 冲突的解决
3 操作接口的实现

0 0
原创粉丝点击