如何解决Hashtable getkType键的摊销时间复杂度如何为O1而不是Olog n?
在最简单的哈希表实现中,通常通过以下方式检索与键关联的索引:
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处的链中收集多少个元素。此后,每个链在统计上应该具有更少的元素。
H(N)
也是直到和包括第N个项的谐波序列的值。尽管没有通用的封闭形式来描述谐波序列,但是可以使用以下公式非常精确地估算该值。
H(N) ≈ ln(N) + 0.5772156649 + 1 / (2N) - 1 / (12N^2)
“近似”部分可以归因于ln(N) + 0.5772156649
之后的项。 ln(N)
是最大的函数,因此摊销的时间复杂度应为 O(log n)
。
有什么我想念的吗?非常感谢您在这里进行澄清。
解决方法
将我的评论扩展为答案-让我们从这里开始:
在最简单的哈希表实现中,通常通过以下方式检索与键关联的索引:
size++; int hash = hashcode(key); int index = hash % size;
实际上并不是大多数哈希表的实现方式。而是,大多数哈希表使用如下策略:
- 选择一些固定的起始插槽数量(例如8、16等)
- 添加元素后,请将其放入插槽
hashcode(key) % tablesize
中。 - 表中项目数与插槽数之比超过称为 负载系数 的阈值后,请执行 哈希 :将表的大小加倍,并通过使用新的表大小重新计算
hashcode(key) % tablesize
来重新分配现有元素。 (最后一步确保在调整表大小的情况下仍可以找到项目,并确保将项目分布在整个表中,而不仅仅是前几个插槽。)
这有多快的确切分析将取决于您如何实现哈希表。如果您使用链式哈希(每个项目都放入插槽中,然后存储在包含该插槽中所有项目的单独数组或链表中),并且您的哈希函数“或多或少”是统一随机的,则(直观上)这些项目可能会或多或少地均匀分布在各个表位上。您可以通过假设您确实具有随机哈希函数来对此进行形式分析,在这种情况下,任何一个插槽中的预期项目数最多为表的负载因子(项目数与插槽数之比) )。通常将负载因子选择为一个常数,这意味着每个插槽的预期项目数由该常数上限,因此可以得出有关O(1)预期查找时间的声明。 (您也可以为线性探测哈希表的查找的预期成本获得相似的O(1)界限,但是数学涉及更多。)
“摊销”部分是由于重新哈希处理步骤而出现的。这个想法是,在大多数情况下,插入操作不会使负载因子超过重新哈希所需的阈值,因此它们的速度非常快。但是有时您确实必须重建表。假设您将表的大小增加了一倍,那么您可以显示出每个重新哈希都以线性插入进行,而这些插入不会触发重新哈希,因此您可以将进行重新哈希所需的工作加重到先前的操作中。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。