标签:位置 数据结构 计算 end 替换 type php 初始化 空间
PHP中的变量名和变量值分别对应的是zval、zend_value,变量的内存是通过引用计数进行管理的,PHP7将引用计数转移到了value中,变量之间的传递赋值也是针对zend_value
php7将布尔类型直接分成了true 、false 两种类型,直接通过type类型划分,因此不需要具体的value。
PHP中字符串没有通过char类型,而是通过zend_string结果,zend_value中通过str指向具体的结构,zend_string除了字符串内容外还有其他具体的信息:
gc:变量的引用计数信息,用于内存管理
h:字符串通过time33算法得到的hashcode,
len:字符串的长度
val:字符串的内容
特殊:存储字符串的内容用了一个可变数组,变长结构体不仅可以节省一次内存的分配,还有助于内存管理,free时直接释放zend_string即可,需要注意的是存储字符串结尾会有一个结束富豪"\0"
数组的底层是散列表也成哈希表,它是根据key-value直接访问的数据结构,它的key-value之间存在映射函数,也就是根据key通过映射函数直接索引到对应的value值,也就是说通过key直接映射到内存中,从而加快了查找速度,理想情况下可以直接知道到待查关键字。
Buckey的结构比较简单,就是key和value,如果元素是数值索引,那它的值就是数值索引的值,如果元素是字符串,那它的key就是通过time33得到的散列值。
数组的基本实现:散列表主要有两部分组成,存储元素数组,散列函数,一个简单的散列函数是通过取模的方式,比如散列表的大小是8,那么散列表初始化元素的时候就给数组分配8个元素大小的空间,根据key的hashcode与8取模得到的值就是该元素的下标,这样就可以通过key映射到存储数组的具体位置。这样实现有个问题就是元素在数组中的位置是随机的,无序的,PHP数组是有序的,为了让散列表实现有序性,PHP中的散列表在散列函数与元素数组之间加了一层映射表,这个映射表也是一个数组,大小与存储元素的数组相同,它的存储元素是整型,用于保存实际的存储的有序数组的下标,元素按照先后顺序一次插入实际存储数组,然后将其数组下标按照散列函数列出来的位置存储在新加的映射表中。
以上就是数组的底层实现原理,但是又会出现一个问题就是哈希冲突,因为time33($key)%size 可能得到的值相同,解决就是将冲突的Bucket串成链表。这里需要注意的是把旧的放到链表中,用新的替换旧的。
查找过程:首先根据key计算出来hashcode以及散列值,然后根据散列值从中间映射表中得到存储元素在有序存储元素的位置idx,接着根据idx从有序村粗数组中取出Bucket,最后从取出的Bucket看 i 啊糇 i遍历,判断Bucket的key是否就是要查找的key,如果是终止遍历,否则继续根据zend.u2.next(用来存放冲突的上面我说的旧的)遍历比较。
扩容:PHP的数组实现了自动扩容,在插入首先会检查是否又空闲空间,当发现空间已满没有位置容纳新元素时就会触发扩容逻辑,扩容之后再执行插入。
引用:数组使用引用时需要注意,引用只能通过&产生,无法通过赋值传递,PHP的引用只是一级。
标签:位置 数据结构 计算 end 替换 type php 初始化 空间
原文地址:https://www.cnblogs.com/weiluoyan/p/8848953.html