# 小结

- 向哈希表中输入一个键 key ，查询到值 value 的时间复杂度为 $O(1)$ ，非常高效。
- 哈希表的常用操作包括查询、添加与删除键值对、遍历键值对等。
- 哈希函数将 key 映射到桶（数组）索引，从而访问到对应的值 value 。
- 两个不同的 key 经过哈希函数可能得到相同的桶索引，进而发生哈希冲突，导致查询错误。
- 缓解哈希冲突的途径有两种：哈希表扩容、优化哈希表的表示方式。
- 负载因子定义为哈希表中元素数量除以桶槽数量，体现哈希冲突的严重程度，常用作哈希表扩容的触发条件。与数组扩容的原理类似，哈希表扩容操作开销也很大。
- 链式地址考虑将单个元素转化成一个链表，将所有冲突元素都存储在一个链表中，从而解决哈希冲突。链表过长会导致查询效率变低，可以通过把链表转化为 AVL 树或红黑树来解决。
- 开放寻址通过多次探测来解决哈希冲突。线性探测使用固定步长，缺点是不能删除元素且容易产生聚集。多次哈希使用多个哈希函数进行探测，相对线性探测不容易产生聚集，代价是多个哈希函数增加了计算量。
- 在工业界中，Java 的 HashMap 采用链式地址、Python 的 Dict 采用开放寻址。
