【发布时间】:2010-12-24 03:57:15
【问题描述】:
首先,我假设我在考虑这个问题时错过了一些重要的事情,但我仍然想发布它,看看我是否真的没有错过任何东西,继续......
我有一个写得很重的二叉树(写和读之间大约 50/50),今天在回家的路上我正在考虑优化它的方法,特别是使写入更快 - 这就是我想出的.
考虑到将 x 添加到树 T 的操作 add(T, x) 首先包含 find(T, x) 以查看 x 是否已经存在,在这种情况下它不会返回父级,因此我们可以添加它而不是父母之一的空叶子。
如果我们在添加操作中添加一个哈希表作为中间缓存,那么当我们调用 add(T, x) 时,真正发生的是 x 被哈希并插入到哈希映射 M 中。就是这样。当我们在其他地方要求 find(T, x) 时进行优化,现在当我们搜索树时,我们将来到叶节点,因为 x 还没有插入树(它只存在于哈希映射 M 中) ,我们散列 x 并将其与 M 中的键进行比较,以查看它是否应该在树中。如果在 M 中找到它,那么我们将它添加到树中并从 M 中删除它。
这将消除对 add(T, x) 的 find(T, x) 操作,并将其简化为 add(M, x),即 O(1)。然后(ab)——使用我们第一次查找节点时执行的find(T, x)操作来插入它。
【问题讨论】:
-
这将需要您维护 2 个结构,并应用足够的散列算法以避免大型结构中的冲突。你看过这个额外的开销吗?
-
@astander:不,我没有,这就是为什么我在这里询问它是否有任何明显的缺陷,我可以在我选择的平台中使用内置的哈希表(. NET),这应该足够好。并且不难检测到冲突(如果我尝试在 M 中的该哈希上插入一个已经存在的值,比较这两个值,如果它们不相等,则在第二个冲突元素上进行正常的二进制插入)
-
另外,您可能想要检查 N 个添加和 N 个查找的复杂性(假设为 50/50),而不是单个添加或查找。我认为你在拖延工作而不是优化工作。
-
@Kathy: 可能是,但是由于键(在这种情况下为字符串)上的比较操作非常繁重(我可以使用非常简单的+快速哈希算法,因为冲突无关紧要)感觉我可以节省很多,尤其是在较大的树上。
-
谨防“碰撞无关紧要”。使用您描述的算法,您的哈希表不允许丢失绑定,因此您不能使用传统缓存中使用的固定长度存储桶。当有很多冲突时,您必须有可扩展的存储桶,这些存储桶会退化为 O(n) 关联列表。
标签: language-agnostic optimization data-structures hashtable binary-tree