数组与线性结构

哈希表

哈希表存放键值对,让你能凭键几乎瞬间查到值。诀窍在于:把键交给一个哈希函数变成一个数字,再用这个数字(对数组大小取模)作为一个桶数组的下标。与其去扫描「alice」,不如算出「alice」必然落在哪里,然后直奔过去。

平均而言,插入、查找和删除都是 O(1)——哈希一步就把你指到正确的桶。麻烦在于冲突:两个不同的键可能哈希到同一个桶。哈希表用链地址法(每个桶挂一条小链表)或开放定址法(探查邻近槽位)来处理。配上好的哈希函数和合理的装载因子(太满时会扩容重哈希),冲突就很少见,O(1) 得以保持。在极坏的最坏情况下——大量冲突——操作会退化为 O(n)。

这份速度的代价是哈希表没有顺序:遍历得到的键是任意的、依赖哈希的次序,你也无法廉价地问「最小的键是谁」。当你需要有序时,平衡树(如 std::map)是替代方案;当你只需要按键快速查找时,哈希表更胜一筹。

#include <unordered_map>
#include <string>
std::unordered_map<std::string, int> age;
age["alice"] = 30;   // average O(1) insert
age["bob"]   = 25;
int a = age["alice"]; // average O(1) lookup -> 30
// buckets:  [0] -> ...
//           [3] -> ("alice",30) -> ("bob",25)   <- a collision, chained
bool has = age.count("carol"); // 0 (not present)

hash(key) % buckets 选出一个桶;冲突在桶内以链表相连。

平均 O(1) 的前提是好的哈希函数和有界的装载因子;若键是对抗性的或哈希很差,查找可能退化为 O(n)。

又称
hash mapdictionaryassociative arrayunordered map哈希表散列表雜湊表散列表(zh)字典