当前位置: 首页 > 后端技术 > PHP

php底层原理的数组实现

时间:2023-03-29 22:16:06 PHP

数组是PHPer中最常用的数据类型。同时,PHP因为数组的强大而使用方便,但是数组在php中是如何实现的呢?首先我们先了解一下相关的数据结构,为后面的内容打下基础。哈希表哈希表,顾名思义,是一种将不同的关键字映射到不同单元的数据结构。将不同的关键字映射到不同的单元的方法称为散列函数。理想情况下,经过hash函数处理后,关键字和单位是一一对应的;但是如果关键字值足够多,那么很容易出现多个关键字映射到同一个单元,也就是哈希冲突。哈希冲突的解决方案要么使用链接方法,要么使用开放寻址方法。链式方式是指当不同的关键字映射到同一个单元时,使用链表将这些关键字保存在同一个单元中开放寻址是指在插入数据时,如果发现关键字映射到的单元有数据,则表示发生了冲突,继续寻找下一个单元,直到找到一个可用的单元为止,因为开放式寻址方案属于占用其他关键字映射单元的位置,后续关键字更容易出现hash冲突,因此很容易导致性能下降。链表既然上面提到了链表,这里就简单说一下链表的基础知识。链表分为很多种。常用的数据结构有:队列、栈、双向链表等链表,它们是由不同的链表节点组成的数据结构。链表节点一般由元素+指向下一个节点的指针组成。双向链表,顾名思义,就是由指向上一个节点的指针+一个元素+指向下一个节点的指针组成。对于数据结构的内容,我们就不过多展开了。后面我们会有专门的内容来详细介绍数据结构。PHP数组php解决hash冲突的方式是使用链接方式,所以php数组是通过hash表+链表实现的。准确的说,内部结构是通过哈希表+双向链表-哈希表实现的HashTable结构主要用来存储哈希表的基本信息typedefstruct_hashtable{uintnTableSize;//hashBucket的大小,即哈希表的容量,最小为8,增加2x。uintnTableMask;//nTableSize-1,索引值优化uintnNumOfElements;//hashBucket中当前存在的元素个数,count()函数会直接返回这个值ulongnNextFreeElement;//下一个可用的数字键ValueBucket*pInternalPointer;//当前遍历指针(foreach比for快的原因之一)Bucket*pListHead;//存储整个哈希表的头元素指针Bucket*pListTail;//存放整个哈希表的尾元素PointerBucket**arBuckets;//存储哈希数组dtor_func_tpDestructor;//删除元素时执行的回调函数,用于资源释放zend_boolpersistent;//指出Bucket内存分配方式。如果persistent为TRUE,则使用操作系统的内存分配函数为Bucket分配内存,否则使用PHP的内存分配函数。无符号字符nApplyCount;//标记当前哈希桶被递归访问的次数(防止多次递归)zend_boolbApplyProtection;//标记当前哈希桶允许多次访问,如果不允许,最多只递归3次#ifZEND_DEBUGintinconsistent;#endif}HashTable;Bucket结构用于保存数据的具体内容typedefstructbucket{ulongh;//char*key散列后的值,或用户指定的数值索引值uintnKeyLength;//hash关键字的长度,如果数组索引是数字,这个值为0void*pData;//指向值,一般是用户数据的一份拷贝,如果是指针数据,指向pDataPtrvoid*pDataPtr;//如果是指针Data,这个值会指向真正的值,上面的pData会指向这个值structbucket*pListNext;//指向整个哈希表中单元的下一个元素structbucket*pListLast;//指向整个哈希表单元的前一个元素structbucket*pNext;//由于hash冲突,指向存储在同一单元的链表中的下一个元素structbucket*pLast;//由于hash冲突指向存储在同一单元的链表中的最后一个元素//保存key字符串为当前值,该字段只能定义在末尾,实现变长结构chararKey[1];}桶;其中Bucket结构中有一个指向用户数据的pData元素,实际上指向了我们之前介绍的变量zval结构,这就是为什么在创建数组的时候,会有一个数组元素+1的变量容器。不了解变量底层知识的可以查看我之前的文章:PHP底层原理之变量(一)PHP底层原理之变量(二)哈希表内部结构关系图注:图片来源于网络。从上图可以看出,Bucket存储数据时,如果出现hash冲突,则将多个关键字映射到链表,从而形成双向链表总结今天我们以数组为切入点,简单介绍一下了解基本数据结构:哈希表和链表;并了解数组的底层实现,即哈希表+双向链表。其实哈希表作为PHP中最重要的数据结构,是非常有用的。变量符号表、函数列表等都存储在哈希表中。有兴趣的同学可以看我之前的文章了解相关知识