Java 哈希表get(kType键)的时间复杂度是如何分摊的O(1)而不是O(logn)?
在哈希表的最简单实现中,与键关联的索引通常按以下方式检索:Java 哈希表get(kType键)的时间复杂度是如何分摊的O(1)而不是O(logn)?,java,data-structures,time-complexity,hashtable,amortized-analysis,Java,Data Structures,Time Complexity,Hashtable,Amortized Analysis,在哈希表的最简单实现中,与键关联的索引通常按以下方式检索: size++; int hash = hashcode(key); int index = hash % size; size++; int hash = hashcode(key); int index = hash % size; 对于任意键,我们可以说索引将是范围[0,size-1]内的整数,每个结果的概率相等。下表描述了添加N个元素后前5个指数的概率 Index | 0 1
size++;
int hash = hashcode(key);
int index = hash % size;
size++;
int hash = hashcode(key);
int index = hash % size;
对于任意键,我们可以说索引将是范围[0,size-1]
内的整数,每个结果的概率相等。下表描述了添加N个元素后前5个指数的概率
Index | 0 1 2 3 4
--------------------------------------------------------------------------------------------
Probabilities | 1
| 1/2 1/2
| 1/3 1/3 1/3
| 1/4 1/4 1/4 1/4
| 1/5 1/5 1/5 1/5 1/5
| ...
| 1/N 1/N 1/N 1/N 1/N
____________________________________________________________________________________________
Total | H(N) H(N) - 1 H(N) - 1.5 H(N) - 1.83 H(N) - 2.08
H(N)
描述了链中索引0处应收集多少元素。之后的每个链都应该具有统计上较少的元素
Index | 0 1 2 3 4
--------------------------------------------------------------------------------------------
Probabilities | 1
| 1/2 1/2
| 1/3 1/3 1/3
| 1/4 1/4 1/4 1/4
| 1/5 1/5 1/5 1/5 1/5
| ...
| 1/N 1/N 1/N 1/N 1/N
____________________________________________________________________________________________
Total | H(N) H(N) - 1 H(N) - 1.5 H(N) - 1.83 H(N) - 2.08
H(N)
也是第N项之前(包括第N项)谐波级数的值。虽然没有描述谐波级数的广义闭合形式,但可以使用以下公式非常精确地近似该值
H(N)≈ ln(N)+0.5772156649+1/(2N)-1/(12N^2)
参考:
“近似”部分可归因于ln(N)+0.5772156649
之后的术语ln(N)
是最大的函数,因此摊销时间复杂度应O(logn)
我有什么遗漏吗?我将非常感谢您在这里进行澄清。将我的评论扩展为一个答案-让我们从这里开始: 在哈希表的最简单实现中,与键关联的索引通常按以下方式检索:
size++;
int hash = hashcode(key);
int index = hash % size;
size++;
int hash = hashcode(key);
int index = hash % size;
实际上,大多数哈希表并不是这样实现的。相反,大多数哈希表使用如下策略:
hashcode(key)%tablesize
hashcode(key)%tablesize
来重新分布现有元素。(最后一步确保在表已调整大小的情况下仍能找到项,并确保项分布在整个表中,而不仅仅是前几个插槽中。)“摊销”部分是由于重新灰化步骤而产生的。这个想法是,大多数情况下,插入不会将负载因子推到重新加载所需的阈值之上,因此它们非常快。但有时您确实需要重建表。假设表的大小是原来的两倍,则可以显示每次重新刷新都是通过线性数量的插入来进行的,而这些插入不会触发重新刷新,因此可以将重新刷新所需的工作量倒扣到以前的操作中。当然,此计算中至少需要两个数字:存储的元素数量,以及哈希表中的桶数。铲斗数量越大,链条的预期长度越短。公式中的桶数在哪里?这是否回答了您的问题?您还忽略了一个事实,即可以随时调整哈希表的大小,以确保只获取一小部分索引(并随后减少每个索引的链接),即“算法X具有复杂性Y”是不明确的。有(至少)三种复杂情况:最坏情况、预期情况和最佳情况。一个典型的哈希表的最坏情况get(即所有键都有相同的哈希)是O(n)。最好的情况通常是O(1)(即所有键都有不同的散列)。预期的大小写取决于预期的散列分布和相对于n的桶数。无限桶将给出O(1),而1桶将给出O(n)。您假设的存储桶数为n+1对于该算法来说并不典型。@khelwood在这个非常简单的实现中,存储桶数为
size
。