二维数组模拟哈希表本质是将桶显式设为数组行(或列),每桶存多个键值对以支持链地址法;适用于算法题、嵌入式、教学等需低依赖、全控场景,核心是确定性哈希函数(如key%m)与桶内线性操作。

用二维数组模拟哈希表,本质是把“桶”显式地做成数组的每一行(或列),每个桶能容纳多个键值对,从而自然支持链地址法处理冲突。这不是替代 PHP 内置哈希表的方案,而是在特定场景下(如算法题、嵌入式环境、教学实现或需完全可控逻辑时)一种清晰、低依赖的建模方式。
明确桶结构与哈希函数
二维数组的第一维代表哈希桶数量(即模数 m),第二维用于存放该桶下的所有键(或键值对)。关键前提是设计一个确定性哈希函数,常见做法是 key % m,确保结果落在 [0, m-1] 范围内。m 通常取质数或略大于预期数据量的整数,有助于分散冲突。
- 若处理的是整数键(如 OJ 题中输入的数字),直接用
key % m得桶号 - 若键是字符串,可先用
crc32($key)或md5截取部分字节再取模,避免负索引 - PHP 中注意数组索引不能为负,建议包裹
abs()或使用($hash % $m + $m) % $m
插入操作:先定位桶,再线性追加
插入一个键 key 时,不覆盖已有同键项,而是检查目标桶内是否已存在该键——这是链地址法保持语义正确性的核心。只有确认不存在时才追加,避免重复。
- 计算桶索引:
$bucket = abs(crc32($key) % $m); - 遍历
$table[$bucket]数组,逐个比对===或==(根据键类型选) - 未命中则
array_push($table[$bucket], $key)或$table[$bucket][] = $key;
查找与删除:桶内顺序扫描
由于二维数组本身不提供自动索引加速,查找和删除都依赖桶内线性遍历。时间复杂度取决于单桶长度,最坏为 O(n),但平均在负载因子合理时接近 O(1)。
- 查找:定位桶后,用
in_array($key, $table[$bucket], true)或手动循环判断 - 删除:找到匹配项的键位置(如
array_search),再用unset或array_splice移除对应元素 - 注意 PHP 中
unset($arr[$i])会留下空洞,如需紧凑索引,后续调用array_values()
存储键值对:扩展第二维为关联结构
纯键集合用途有限,多数场景需存 key → value 映射。此时第二维不再存单一值,而应为子数组,例如 ['key' => 'value'] 或 [$key, $value] 形式。
- 插入:
$table[$bucket][] = ['k' => $key, 'v' => $value]; - 查找:
foreach ($table[$bucket] as $pair) { if ($pair['k'] === $key) return $pair['v']; } - 为提升可读性,也可用
array_column($table[$bucket], 'v', 'k')构建临时映射,但注意这会复制数据,慎用于大桶











