Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Data structures 为什么要用二进制搜索树实现哈希表?_Data Structures_Hashtable_Binary Search Tree - Fatal编程技术网

Data structures 为什么要用二进制搜索树实现哈希表?

Data structures 为什么要用二进制搜索树实现哈希表?,data-structures,hashtable,binary-search-tree,Data Structures,Hashtable,Binary Search Tree,当使用数组实现哈希表时,我们继承了数组的常量时间索引。既然哈希表提供了使用O(logn)进行搜索,那么使用二进制搜索树实现哈希表的原因是什么?为什么不直接使用二元搜索树呢?如果元素没有a(即没有为所有对定义“大于”和“小于”,或者元素之间不一致),则无法比较所有对,因此无法直接使用BST,但是没有什么能阻止您通过散列值对BST进行索引-因为这是一个整数值,它显然有一个总的顺序(尽管您仍然需要,也就是说有一种方法可以处理具有相同散列值的元素) 然而,与哈希表相比,BST的最大优点之一是元素是有序的

当使用数组实现哈希表时,我们继承了数组的常量时间索引。既然哈希表提供了使用O(logn)进行搜索,那么使用二进制搜索树实现哈希表的原因是什么?为什么不直接使用二元搜索树呢?

如果元素没有a(即没有为所有对定义“大于”和“小于”,或者元素之间不一致),则无法比较所有对,因此无法直接使用BST,但是没有什么能阻止您通过散列值对BST进行索引-因为这是一个整数值,它显然有一个总的顺序(尽管您仍然需要,也就是说有一种方法可以处理具有相同散列值的元素)

然而,与哈希表相比,BST的最大优点之一是元素是有序的——如果我们按哈希值排序,元素将具有任意顺序,而这一优点将不再适用

至于为什么可以考虑使用BST而不是数组来实现哈希表,它将:

  • 没有需要调整数组大小的缺点-对于数组,通常使用数组大小修改哈希值,并在数组满时调整数组大小,重新插入所有元素,但是对于BST,您可以直接将不变的哈希值插入BST

    如果我们希望任何单个操作所花费的时间都不会超过一定的时间(如果需要调整阵列大小,很可能会发生这种情况),并且总体性能是次要的,那么这可能是相关的,但是可能有更好的方法来解决此问题

  • 减少了散列冲突的风险,因为您不需要修改数组大小,因此可能的散列数可能会大大增加。这将降低获得哈希表最坏性能的风险(当元素的很大一部分哈希到相同的值时)

    实际最坏情况下的性能取决于您解决冲突的方式。这通常是通过O(n)最坏情况性能的链表完成的。但我们也可以使用BST实现O(logn)性能(如中所做的,如果具有某些散列的元素数高于阈值),也就是说,使用散列表数组,其中每个元素指向一个BST,其中所有元素都具有相同的散列值

  • 可能使用更少的内存-对于数组,不可避免地会有一些空索引,但对于BST,这些索引根本不需要存在。虽然这不是一个明确的优势,但如果这是一个优势的话

    如果我们假设使用不太常见的,那么这个数组也会有一些空索引,这也需要偶尔调整大小,但这只是一个内存拷贝,而不需要使用更新的哈希重新插入所有元素

    如果我们使用典型的基于指针的BST实现,指针的额外成本似乎会超过在数组中拥有几个空索引的成本(除非数组特别稀疏,这对于哈希表来说往往是一个坏迹象)

但是,因为我个人从来没有听说过这样做,所以从预期的O(1)到O(logn)的运营成本增加,可能带来的好处并不值得


通常情况下,可以在直接使用BST(无哈希值)和使用哈希表(带数组)之间进行选择。

由于哈希表的要求是O(1)查找,如果它具有对数查找时间,则它不是哈希表。诚然,由于冲突是阵列实现的一个问题(嗯,不太可能是问题),所以使用BST可以在这方面提供好处。不过,一般来说,这不值得权衡——我想不出在使用哈希表时,您不希望保证O(1)查找时间的情况

或者,也可以使用底层结构通过BST变量来保证对数插入和删除,其中数组中的每个索引都有一个对BST中相应节点的引用。这样的结构可能会有点复杂,但可以保证O(1)查找和O(logn)插入/删除。

优点:

  • 可能使用更少的空间b/c我们不分配大型阵列
  • 可以按顺序遍历键,有时很有用
  • 缺点:

  • 您将有O(logn)查找时间,这比链式哈希表保证的O(1)更糟糕

  • 我发现这个是为了看看有没有人做过。我想也许不是

    今天早上我想到了一个想法,将二叉树实现为一个数组,由索引存储的行组成。第1行有1,第2行有2,第3行有4(是的,二的幂)。这种结构的优点是位移位,可以使用加法或减法遍历树,而不是使用额外的内存来存储双向或单向引用

    这将允许您基于某种可哈希输入快速搜索哈希值,以发现该值是否存在于其他存储中。或用于哈希冲突(或部分冲突)搜索。我想不出它还有什么其他用途,但对于这些用途,它的速度会非常快。很多旋转操作很可能完全发生在cpu缓存中,并以漂亮的线性块写入主内存

    它的主要用途是对随机性质的输入值进行排序。如果数组中的blob是两部分,比如散列和另一个存储的标识符,那么可以非常快速地进行比较并插入,以发现带有散列值的项保存在另一个位置的位置(比如文件系统节点的UUID,甚至可能是文件名,或者其他短的可识别字符串)

    我将把它留给其他人去梦想使用它的其他方式,但我正在使用它作为identi的图论工作证明搜索表