在閱讀了zend/zend_hash.h和ext/standard/array.c之後,我想我已經找到了答案(謝謝Chris和gumbo的建議)。
PHP數組是一個鏈式哈希表(在關鍵衝突中查找O(c)和O(n)),允許使用int和string鍵。它使用2種不同的哈希算法將兩種類型合併到相同的哈希鍵空間中。另外,存儲在散列中的每個值都與其之前存儲的值以及存儲在(鏈接列表)之後的值鏈接。它還有一個臨時指針,用於保存當前項目,以便迭代散列。
array_rand
函數的捕獲是爲了確保密鑰真正是隨機的,函數必須遍歷數組rand(0, count($array))
次(O(n))。這是因爲無法在O(c)時間移動到散列表中的偏移量,因爲不能保證範圍內沒有丟失鍵。
這個發現讓我有點困擾,因爲這意味着PHP中沒有數據類型,它具有正常的C數組特性。現在大多數情況下這是可以的,因爲哈希查找速度非常快,但在array_rand
等情況下會顯示錯誤。
另一件令我困擾的事情是實施array_key_exists
和in_array
之間的區別。 array_key_exists
使用散列查找(大部分時間O(c))來查看密鑰是否在數組中,而in_array
必須線性搜索散列(O(n))。
考慮下面的兩個例子:
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)或關閉)。
總之: 我希望有在將在其中陣列是使用array_push
或array[] = $value
創建情況下,將允許用於縮放像C數組代替鏈接的設置了Zend哈希表的數據結構的透明標誌名單。
看看源代碼:http://svn.php.net/viewvc/php/php-src/trunk/ext/spl/spl_array.c?view=markup – Gumbo 2010-02-28 16:01:12
@Gumbo,鏈接.. ... – Pacerier 2013-07-27 13:59:04
@Prier這是[Github存儲庫中的文件](https://github.com/php/php-src/blob/master/ext/spl/spl_array.c)。 – Gumbo 2013-07-27 15:14:55