PHP 陣列底層採用 Hash Table 實現。當不同鍵值經過雜湊函式計算出相同索引時,即發生「碰撞」。本文透過實際測試示範碰撞現象,並以「拉鏈法」完整實作解決方案。
<?php
$ht = new HashTable();
$ht->insert('key1', 'value1');
$ht->insert('key12', 'value12'); // 與 key1 雜湊值相同(假設簡易演算法)
echo $ht->find('key1'); // 預期 value1,實際輸出 value12(被覆蓋)
echo $ht->find('key12'); // 輸出 value12
?>
原因:簡易雜湊函式將字串 ASCII 碼相加,key1 與 key12 皆得 8,導致同一索引位置被覆寫。
將相同雜湊值的節點串成鏈表,查找時遍歷鏈表比對原始鍵值。
<?php
class HashNode {
public $key;
public $value;
public $nextNode;
public function __construct($key, $value, $nextNode = null) {
$this->key = $key;
$this->value = $value;
$this->nextNode = $nextNode;
}
}
?>
public function insert($key, $value) {
$index = $this->hashFunc($key);
if (isset($this->buckets[$index])) {
// 碰撞:新節點指向舊節點,成為新頭部
$newNode = new HashNode($key, $value, $this->buckets[$index]);
} else {
$newNode = new HashNode($key, $value, null);
}
$this->buckets[$index] = $newNode;
}
public function find($key) {
$index = $this->hashFunc($key);
$current = $this->buckets[$index];
while (isset($current)) {
if ($current->key === $key) {
return $current->value; // 找到
}
$current = $current->nextNode; // 遍歷下一節點
}
return null; // 未找到
}
nextNode 指向舊頭部 → 更新桶位指向新節點。key → 相等回傳 value → 遍歷結束回傳 null。| 操作 | 平均情況 | 最壞情況 |
|---|---|---|
| 插入 | O(1) | O(n) (所有鍵碰撞) |
| 查找 | O(1) | O(n) |
| 刪除 | O(1) | O(n) |
良好的雜湊函式與負載因子控制(擴容)可維持平均 O(1)。
zend_ulong 整數雜湊,支援字串與整數鍵的混合儲存。