下面是PHP数组的基本结构,插入,查找,rehash过程。基础结构:struct_zend_array{zend_refcounted_hgc;union{struct{ZEND_ENDIAN_LOHI_4(zend_ucharflags,zend_ucharnApplyCount,zend_ucharnIteratorsCount,zend_ucharconsistency)}v;uint32_t标志;}你;uint32_tnTableMask;//哈希值计算码,等于nTableSize(nTableMask=-nTableSize)Bucket的负值*arData;//存储元素数组,指向第一个Bucketuint32_tnNumUsed;//使用的桶数uint32_tnNumOfElements;//哈希表中元素的有效数量=nNumUsed-num(is_undef)uint32_tnTableSize;//哈希表总大小为2的n次方,最小为8uint32_tnInternalPointer;//怀疑是内部指针zend_longnNextFreeElement;//下一个可用的数值索引arr[]=1;arr["a"]=2;arr[]=3;然后nNextFreeElement=2;dtor_func_tpDestructor;};typedefstruct_Bucket{zvalval;//具体的存储值zend_ulongh;//哈希值(或数字索引x)zend_string*键;//字符串键或数字为NULL}Bucket;说明:存储数组时,先按顺序存储值,再存储值的位置,存储记录。该数组称为哈希表。该数组用于存储值。value是按顺序存储的,它的存储位置会存储在通过计算key的hash并对nTableMask取模得到的idx中。初始化数组时,最小大小为8,因此为16、32、64。。.数组初始化的时候会把idx区初始化为-1,rehash的时候也会初始化为-1。当删除数组中的一个元素时,标记被删除元素的类型为is_undef,nNumOfEmelment-1,如果该元素是最后一个元素,则nNumUsed-1。插入:取$arr=['a'=>1,'b'=>2]为例:先把1放入数组,它的val.u2.next=-1,根据它的下标a计算hash,然后hash取模nTableMask得到一个idx,存入索引nindex为1在idx的位置。然后存2,其val.u2.next=-1,如果根据其下标b计算hash取模nTableMask得到的idx中已经有值,则说明存在hash冲突,而在这次,将当前idx中的值保存到当前的val.u2.next中,保存当前idx中2的索引nindex,以此类推。搜索:根据下标a计算hash取模nTableMask得到一个idx,取idx中的值nindex去arData中搜索,如果找到的位置的key!=a,则找不到;如果找到的位置key==a中的key,则查看其u2.next,如果为-1,则找到;如果不为-1,则说明插入过程中存在hash冲突,则继续根据u2.next在arData中查找,直到找到为止。rehash:rehash时,先将nindex区的所有记录重置为-1,然后将指针*p从第一个元素移开。如果元素没有被标记为is_undef,则重新计算元素的keyhash,放入nindex,然后循环,p++。如果元素标记为is_undef,则继续移动指针p++,并设置一个新的指针j指向该位置,继续循环,将不为is_undef的元素一个一个移到前面,每次p移动,j遇到is_undef不移动直到赋值。移动到最后一个nNunUsed,然后把j赋值给nNunUsed,然后从这个位置插入元素,前面的元素会直接被覆盖。
