在阅读了zend/zend_hash.h和ext/standard/array.c之后,我想我已经找到了答案(感谢Chris和gumbo的建议)。
PHP 数组是一个链式哈希表(在键冲突时查找 O(c) 和 O(n)),它允许使用 int 键和字符串键。它使用 2 种不同的哈希算法将两种类型拟合到同一哈希密钥空间中。此外,存储在哈希中的每个值都链接到它之前存储的值和存储在它之后的值(链接列表)。它还具有一个临时指针,用于保存当前项,以便可以迭代哈希。
该函数的捕获点是,为了确保键是真正随机的,该函数必须迭代数组时间(O(n))。这是因为无法在 O(c) 时间内移动到哈希表中的偏移量,因为无法保证该范围内没有缺少键。array_rand
array_rand
rand(0, count($array))
这一发现有点困扰我,因为这意味着PHP中没有具有正常C数组特征的数据类型。现在大多数时候这是可以的,因为哈希查找非常快,但是在这样的情况下,它的错误会显示出来。array_rand
另一件同样困扰我的是 和 的实现之间的差异。 使用哈希查找(大多数情况下为 O(c))来查看数组中是否有键,而必须线性搜索哈希 (O(n))。array_key_exists
in_array
array_key_exists
in_array
请考虑以下两个示例:
in_array版本
$array = range(0, 100000);
if( in_array( $random_key, $array ) ) {
//we found a value
}
array_key_exists版本
$array = array_fill_keys( range(0, 100000), NULL );
if( array_key_exists( $random_key, $array ) ) {
//we found a value, err key
}
虽然in_array版本看起来更干净,更容易理解,但它实际上在大型数组(O(n))上非常慢,其中array_key_exists(尽管名称很长)非常快(O(c)或接近)。
总之:我希望在zend HashTable数据结构中有一个透明标志,可以在使用数组创建的情况下设置,或者允许像C数组而不是链表一样扩展。array_push
array[] = $value