Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.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
C 哈希表是如何在流行语言中内部实现的?_C_Hashtable - Fatal编程技术网

C 哈希表是如何在流行语言中内部实现的?

C 哈希表是如何在流行语言中内部实现的?,c,hashtable,C,Hashtable,有人能解释一下像Python、Ruby这样的流行语言是如何在内部为符号查找实现哈希表的吗?他们是使用经典的“链表数组”方法,还是使用平衡树 我需要一种简单(更少的LOC)和快速的方法来索引用C编写的DSL中的符号。我想知道其他人发现什么是最有效和实用的。平衡树有点违背了哈希表的目的,因为哈希表可以在(摊销)恒定时间内提供查找,而平衡树上的平均查找是O(log(n)) 如果有足够的bucket,单独链接(带有链表的数组)确实可以很好地工作,并且链表实现使用池分配器,而不是malloc()将堆中的每

有人能解释一下像Python、Ruby这样的流行语言是如何在内部为符号查找实现哈希表的吗?他们是使用经典的“链表数组”方法,还是使用平衡树


我需要一种简单(更少的LOC)和快速的方法来索引用C编写的DSL中的符号。我想知道其他人发现什么是最有效和实用的。

平衡树有点违背了哈希表的目的,因为哈希表可以在(摊销)恒定时间内提供查找,而平衡树上的平均查找是O(log(n))

如果有足够的bucket,单独链接(带有链表的数组)确实可以很好地工作,并且链表实现使用池分配器,而不是malloc()将堆中的每个节点单独链接起来。我发现,经过适当调整后,它的性能几乎与其他任何技术一样,而且编写起来非常简单和快速。尝试从源数据的1/8个存储桶开始

您也可以使用二次或多项式探测。

有a和a。
源代码是可用的,它是用C和C++编写的。

Crashworks的意思是

哈希表的用途是定时查找、添加和删除。就算法而言,所有操作的操作均为O(1)摊销。 然而,在使用树的情况下……对于平衡树,最坏情况下的操作时间将是O(logn)。N是节点数。但是,我们真的将哈希实现为树吗?

您提到的经典“哈希桶数组”在我所看到的每个实现中都使用


最具教育意义的版本之一是Tcl语言的哈希实现,在文件中。文件中超过一半的行是注释,详细解释了所有内容:分配、搜索、不同的哈希表类型、策略等。旁注:实现Tcl语言的代码非常可读。

Perl使用带有链接列表的数组来保存冲突。它有一个简单的启发式方法,可以根据需要自动将数组的大小增加一倍。还有一些代码可以在散列之间共享密钥,以节省一些内存。您可以在“HV”下注明日期但仍然相关的文档中阅读。如果你真的喜欢冒险,你可以深入研究

哈希算法过去非常简单,但现在使用Unicode可能要复杂得多。由于该算法是可预测的,因此存在DoS攻击,攻击者通过该攻击生成的数据会导致哈希冲突。例如,作为POST数据发送到网站的大量密钥列表。Perl程序可能会将其拆分并转储为哈希,然后将其全部放入一个桶中。得到的散列是O(n)而不是O(1)。在服务器上抛出大量POST请求,可能会阻塞CPU。结果,Perl现在用一点随机数据扰乱哈希函数

您可能还想看看哪一个比Perl5实现要安全得多


至于“最有效、最实用”,请使用其他人的哈希库。看在上帝的份上,不要自己写一本供生产使用。已经有无数健壮而高效的映射实现了。

如果你能阅读
Java
,你可能想查看它的各种映射实现的源代码,特别是
HashMap
TreeMap
ConcurrentSkipListMap
。后两者保持钥匙的有序

Java的
HashMap
使用了您提到的在每个bucket位置链接的标准技术。它使用相当弱的32位哈希代码,并将键存储在表中。数字配方的作者还给出了一个散列表的示例(C),该散列表的结构与Java的基本相似,但其中(a)从数组中分配桶列表的节点,以及(b)您可以使用更强的64位哈希代码,而无需将键存储在表中。

表使用一个数组,该数组对任意键的行为类似于“bucket数组”,但如果您使用连续整数作为键,则其表示形式和空间开销与数组相同。在实现中,每个表都有一个哈希部分和一个数组部分


我认为这很酷:-)

也许你想问“映射是如何实现的…”,因为哈希表不是实现映射的唯一方法!好评论。但问题是我已经根据符号的计算散列构建了基础工作。顺便说一句,除了散列(我认为每个人都使用散列)之外,映射还有什么其他的实现方式?映射有时也是从二叉树构建的。它通常用于密钥类型不可破坏,或者您希望在映射中保留数据的特定顺序(以便可以从a到Z进行迭代)。对数失败常数时间?@tydok-为了“击败目标”,意味着无法满足其他解决方案满足的任何目标,因此它意味着“比差”,而不是“比好”。感谢您指出我的不足之处--我已经修复了我的答案。作为树实现的哈希是一个前面有类似哈希的API的树。如果使用ifdeffery,代码的早期版本由于数量减少而更具可读性,尽管更高版本在关键方面更有用(支持密钥自定义和其他类似的功能)。在Java中,
TreeMap
基于红黑树实现,
ConcurrentSkipListMap
基于SkipList实现。