最近面试遇到这个,因为自己已经开始自我嫌弃php了,之前准备的时候就没看这块了,现在被问了主语言,不会就他喵的很尴尬了,补一补~
介绍
PHP 的数组是很强大且很重要的数据类型,它既支持单纯的数组又支持键值对数组,其中键值对数组类似于 Go 语言的map但又保证了能够按顺序遍历,并且由于采用了哈希表实现能够保证基本查找时间复杂度为 O(1)。所以接下来让我们了解一下 PHP 数组的底层实现吧~
数组的数据结构
一个数组在 PHP 内核里是长什么样的呢?我们可以从 PHP 的源码里看到其结构如下:
1、nNumUsed和nNumOfElements的区别:nNumUsed指的是arData数组中已使用的Bucket数,因为数组在删除元素后只是将该元素Bucket对应值的类型设置为IS_UNDEF(因为如果每次删除元素都要将数组移动并重新索引太浪费时间),而nNumOfElements对应的是数组中真正的元素个数。
2、nTableSize数组的容量,该值为 2 的幂次方。PHP 的数组是不定长度但 C 语言的数组定长的,为了实现 PHP 的不定长数组的功能,采用了「扩容」的机制,就是在每次插入元素的时候判断nTableSize是否足以储存。如果不足则重新申请 2 倍nTableSize大小的新数组,并将原数组复制过来(此时正是清除原数组中类型为IS_UNDEF元素的时机)并且重新索引。
3、nNextFreeElement保存下一个可用数字索引,例如在 PHP 中$a[] = 1;这种用法将插入一个索引为nNextFreeElement的元素,然后nNextFreeElement自增 1。
_zend_array 这个结构先讲到这里,有些结构体成员的作用在下文会解释,不用紧张O(∩_∩)O哈哈~。下面来看看作为数组成员的 Bucket 结构:
typedef struct _Bucket {
// 数组元素的值
zval val;
// key 通过 Time 33 算法计算得到的哈希值或数字索引
zend_ulong h;
// 字符键名,数字索引则为 NULL
zend_string *key;
} Bucket;
网友评论