unordered 系列关联式容器
unordered_map, unordered_set, unordered_multimap, unordered_multiset 均基于哈希表实现。它们的接口与 set/map 类似,支持范围 for 遍历。
主要区别:
- 迭代器为单向迭代器。
- 遍历时不保证有序。
- 性能通常优于红黑树实现的容器(如
std::set),但在数据已排序插入场景下,树结构可能更优。
注意:性能对比建议在 Release 模式下进行。
哈希基础
哈希(散列)通过建立值与存储位置的映射关系来提高查询效率,本质是以空间换时间。常用方法包括:
- 直接定址法:适用于值分布集中的场景(如统计字符出现次数)。
- 除留余数法:适用于值分布分散的场景,公式通常为
key % n。
哈希冲突处理
当不同键映射到同一位置时发生冲突,常见解决方案有:
- 闭散列(开放定址法):当前位置被占用时,按规则寻找下一个空位。包括线性探测和二次探测。
- 开散列(链地址法):即哈希桶,每个位置挂一个链表。
闭散列模拟实现
采用除留余数法配合线性探测。状态标记使用 EXIST, EMPTY, DELETE,其中 DELETE 用于解决删除后填充空洞的问题,扩容时需跳过 DELETE 状态。
enum STATE { EXIST, EMPTY, DELETE };
template<class K, class V>
struct HashData {
pair<K, V> _kv;
STATE _state = EMPTY;
};
template<class K>
struct DefaultHashFunc {
size_t operator()(const K& key) {
return (size_t)key;
}
};
template<class K, , = DefaultHashFunc<K>>
HashTable {
:
() { _table.(); }
{
(_n * / _table.() >= ) {
newSize = _table.() * ;
HashTable<K, V, HashFunc> newHT;
newHT._table.(newSize);
( i = ; i < _table.(); ++i) {
(_table[i]._state == EXIST) {
newHT.(_table[i]._kv);
}
}
_table.(newHT._table);
}
HashFunc hf;
hashi = (kv.first) % _table.();
(_table[hashi]._state == EXIST) {
++hashi;
hashi %= _table.();
}
_table[hashi]._kv = kv;
_table[hashi]._state = EXIST;
++_n;
;
}
{
HashFunc hf;
hashi = (key) % _table.();
(_table[hashi]._state != EMPTY) {
(_table[hashi]._state == EXIST && _table[hashi]._kv.first == key) {
(HashData< K, V>*)&_table[hashi];
}
++hashi;
hashi %= _table.();
}
;
}
{
HashData< K, V>* ret = (key);
(ret) {
ret->_state = DELETE;
--_n;
;
}
;
}
:
vector<HashData<K, V>> _table;
_n = ;
};


