|
|
|
@ -18,14 +18,14 @@
|
|
|
|
|
|
|
|
|
|
!!! question "哈希表的时间复杂度为什么不是 $O(n)$ ?"
|
|
|
|
|
|
|
|
|
|
当哈希冲突比较严重时,哈希表的时间复杂度会退化至 $O(n)$ 。当哈希函数设计的比较好、容量设置比较合理、冲突比较平均时,时间复杂度是 $O(1)$ 。我们使用编程语言内置的哈希表时,通常认为时间复杂度是 $O(1)$ 。
|
|
|
|
|
当哈希冲突比较严重时,哈希表的时间复杂度会退化至 $O(n)$ 。当哈希函数设计的比较好、容量设置比较合理、冲突比较平均时,时间复杂度是 $O(1)$ 。我们使用编程语言内置的哈希表时,通常认为时间复杂度是 $O(1)$ 。
|
|
|
|
|
|
|
|
|
|
!!! question "为什么不使用哈希函数 $f(x) = x$ 呢?这样就不会有冲突了"
|
|
|
|
|
|
|
|
|
|
在 $f(x) = x$ 哈希函数下,每个元素对应唯一的桶索引,这与数组等价。然而,输入空间通常远大于输出空间(数组长度),因此哈希函数的最后一步往往是对数组长度取模。换句话说,哈希表的目标是将一个较大的状态空间映射到一个较小的空间,并提供 $O(1)$ 的查询效率。
|
|
|
|
|
|
|
|
|
|
!!! question "哈希表底层实现是数组、链表、二叉树,但为什么效率可以比他们更高呢?"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
首先,哈希表的时间效率变高,但空间效率变低了。哈希表有相当一部分的内存是未使用的,
|
|
|
|
|
|
|
|
|
|
其次,只是在特定使用场景下时间效率变高了。如果一个功能能够在相同的时间复杂度下使用数组或链表实现,那么通常比哈希表更快。这是因为哈希函数计算需要开销,时间复杂度的常数项更大。
|
|
|
|
@ -33,7 +33,7 @@
|
|
|
|
|
最后,哈希表的时间复杂度可能发生劣化。例如在链式地址中,我们采取在链表或红黑树中执行查找操作,仍然有退化至 $O(n)$ 时间的风险。
|
|
|
|
|
|
|
|
|
|
!!! question "多次哈希有不能直接删除元素的缺陷吗?对于标记已删除的空间,这个空间还能再次使用吗?"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
多次哈希是开放寻址的一种,开放寻址法都有不能直接删除元素的缺陷,需要通过标记删除。被标记为已删除的空间是可以再次被使用的。当将新元素插入哈希表,并且通过哈希函数找到了被标记为已删除的位置时,该位置可以被新的元素使用。这样做既能保持哈希表的探测序列不变,又能保证哈希表的空间使用率。
|
|
|
|
|
|
|
|
|
|
!!! question "为什么在线性探测中,查找元素的时候会出现哈希冲突呢?"
|
|
|
|
|