是否可以通过使用二进制搜索树进行单独链接来加快哈希表的速度?


11

我想使用二进制搜索树实现哈希表,以减少从O(n)(使用链表)到O(log n)(使用BST)的单独链接过程中的搜索复杂性。可以这样做,如果可以,怎么办?如果解决方案是逐步实施的,则逻辑将更容易理解。

我想减少哈希表中的“搜索”时间(使用单独的链接进行构建),但同时我不想增加插入时间。对于我的项目,我无法更改哈希函数以减少冲突。但是由于可伸缩性,冲突正在发生。我试图找到一种解决方法,以便在发生冲突的情况下以某种方式使用最佳访问并插入时间...即管理事物的当前状态,而不是重构整个算法。如果没有成功,则必须进行重组。有什么想法吗?


4
哈希表和二进制搜索树是不同的容器。因此,您无法做您所建议的操作(或者您犯了术语错误)。
Basile Starynkevitch 2015年

我猜您可以在树中的每个节点中放置一个哈希/值对...但是那将是错误的哈希表或错误的二叉树。在没有明确说明为什么要执行此操作以及希望最终结果具有什么功能的情况下,我不确定这是否确实可行。
Ixrec 2015年

1
@AK_:是的,就像你说的那样。我想使用二进制搜索树来处理冲突。我更正了我的问题,使其更加清楚。
2015年

1
请注意,随后每次插入都会带来O(n log n)的损失。通常,当您的哈希表开始变得太满(并且链长得无法忍受)时,您将重建哈希。如果您经常遇到链长超过3或4的问题,那是错误的。

3
哈希表在减少冲突,开放寻址和动态调整表大小方面有无数种变化。您需要研究哪一项符合您的要求。您当前的方法包含在与其他结构的单独链接中

Answers:


11

考虑到您的限制,您所要求的是可能的。

分析

哈希表的优势在于其快速的查找和插入速度。为了获得这种速度,必须放弃表中的任何顺序的外观:即,所有条目都被弄乱了。列表可以用作表条目,因为遍历为O(n)时,假设哈希表足够大,并且使用高质量的哈希算法对存储在表中的对象进行哈希处理,则列表往往较短。

二进制搜索树(BST)具有快速插入和查找O(log 2 n)的能力。它还对它存储的元素施加了限制:必须有某种方式来排序元素。给定存储在树中的两个元素AB,必须能够确定A是否在B之前,或者它们是否具有相等的顺序。

哈希表没有施加任何限制:哈希表中的元素必须具有两个属性。首先,必须有一种方法来确定它们是否等效;其次,必须有一种计算确定性哈希码的方法。订单不是必需的。

如果您的哈希表元素确实具有顺序,则可以将BST用作哈希表条目,以保存具有相同哈希码(冲突)的对象。但是,由于具有O(log 2 n)查找和插入的BST ,这意味着整个结构(哈希表加BST)的最坏情况在技术上要比使用列表作为表条目更好。根据BST的实现,它将需要比列表更多的存储空间,但可能不会更多。

请注意,通常是BST的开销和行为带来什么表在现实世界作为哈希表桶,这就是为什么列表的理论性能差是可以接受的。换句话说,哈希表通过在每个列表(存储桶)中放置较少的项来补偿列表的弱点。但是:问题特别指出,哈希表无法增加大小,并且冲突比哈希表中的典型情况更为频繁。

实作

我不会在这里放置代码,因为说实话这不是真正必要的,而且您也没有提供任何语言。

我要做的就是简单地将您语言的标准库包含的任何标准哈希表复制到新类中,然后将表存储桶类型从列表更改为树。根据语言及其标准库,这可能是一件非常琐碎的事情。

通常,我不会提倡像这样复制和粘贴代码。但是,这是一种非常快速地获得经过测试的数据结构的简便方法。


用渐近的术语来说,使用二叉树进行冲突处理不会改变哈希表的预期性能,只要该哈希表已经执行了通常的技巧即可获得摊销的O(1)性能。调整哈希表的大小以确保良好的性能意味着每个存储桶的预期项目(二叉树的大小)也应该很小,因此无论哪种方式,您最终都得到相同的预期摊销O(1)。即使在最坏的情况下(未指定任何平衡约束),二叉树的最坏情况性能也仍然是其最终表现像链表。
Steve314,2015年

@ Steve314请记住,问题在于存在很多冲突,因此他希望存储桶比散列表通常包含更多的项。

优点-例如,对于具有无限制数据的恒定大小的哈希表,哈希表的渐近性能与冲突处理的渐近性能相同-哈希表仅更改常数因子。
Steve314,2015年

@ Steve314,基本上,如果哈希表不能有效地限制每个存储桶中元素的数量,则渐进性能会降低到每个存储桶中使用的子数据结构。我在回答中添加了一个段落以明确说明。

7

在哈希表中使用二进制树进行冲突处理不仅是可能的,而且已经做到了。

沃尔特·布赖特Walter Bright)D编程语言的发明家,但他还编写了ECMAScript变体DMDScript。过去,DMDScript(或可能是祖先-我似乎还记得DScript)的标题是它的哈希表往往胜过许多类似语言的哈希表。原因-使用二叉树进行冲突处理。

我不记得确切的来源,但是使用的树是幼稚的二叉树,没有部分平衡方案(不是AVL,红黑或其他),这可以假设哈希表本身在变得过满时会重新调整大小,您不会得到令人难以置信的哈​​希冲突率,二叉树应该总是很小。基本上,最坏的情况仍然与使用链表进行冲突处理相同(除了您要为每个节点支付两个指针而不是一个指针的代价),但是平均情况会减少每个哈希存储桶中的搜索量。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.