在我具有用于每个元件的一个关键,我不知道元件到一个数组的索引的情况下,哈希表的性能比阵列更好(O(1)与O(N))。
这是为什么? 我的意思是:我有钥匙,我哈希它..我有散..不应该的算法比较对每一个元素的hash该哈希? 我觉得有内存配置背后的一些伎俩,不是吗?
在我具有用于每个元件的一个关键,我不知道元件到一个数组的索引的情况下,哈希表的性能比阵列更好(O(1)与O(N))。
这是为什么? 我的意思是:我有钥匙,我哈希它..我有散..不应该的算法比较对每一个元素的hash该哈希? 我觉得有内存配置背后的一些伎俩,不是吗?
在我具有用于每个元件的一个关键,我不知道元件到一个数组的索引的情况下,哈希表的性能比阵列更好(O(1)与O(N))。
哈希表搜索在平均情况下进行O(1)。 在最坏的情况下,哈希表搜索执行O(N):当你有碰撞和哈希函数总是返回相同的插槽。 有人可能会认为“这是一个远程的情况,”但一个好的分析应该考虑一下。 在这种情况下,应该通过所有像在阵列或链接的列表(O(N))中的元素进行迭代。
这是为什么? 我的意思是:我有钥匙,我哈希它..我有散..不应该的算法比较对每一个元素的hash该哈希? 我觉得有内存配置背后的一些伎俩,不是吗?
你有钥匙,你凑吧..你有哈希:哈希表的索引,其中元素存在(如果它已经位于前)。 在这一点上,你可以访问哈希表记录在O(1)。 如果负载系数小,它不可能看到有一个以上的元素。 所以,你看到的第一要素应该是你正在寻找的元素。 否则,如果你有一个以上的元素,你必须比较,你会在你正在寻找该元素的位置找到的元素。 在这种情况下,你有O(1)+ O(number_of_elements)。
在平均情况下,哈希表搜索复杂度为O(1)+ O(load_factor)= O(1 + load_factor)。
请记住,load_factor = N在最坏的情况下。 所以,搜索的复杂性是在最坏情况下为O(n)。
我不知道你的意思“内存配置背后的猫腻”是什么。 在的一些观点,哈希表(通过链接它的结构和碰撞分辨率)可以被认为是一个“聪明诡计”。
当然,哈希表的分析结果可以用数学证明。
使用数组 :如果你知道的价值,你必须在平均水平的一半搜索值(除非排序)找到自己的位置。
与散列 :基于该值产生的位置。 因此,再次获得该值,就可以计算出你插入时计算相同的散列。 有时,超过1周的值的结果在相同的散列,所以在实践中每一个“位置”是本身散列到该位置的所有值的阵列 (或链表)。 在这种情况下,只有这个小很多(除非它是一个坏哈希)阵列需要搜索。
哈希表是一个有点复杂。 他们把基于其散列%一定的价值不同的桶的元素。 在理想的情况下,每个桶持有非常少的项目,不会有太多的空水桶。
一旦你知道键,你计算哈希值。 基于哈希,你知道要寻找为其桶。 并且如上所述,每个桶中的项目数应该是比较小的。
哈希表在内部做了很多的魔法,以确保桶尽可能小,且不消耗的空水桶太多内存。 此外,很大程度上取决于质量的关键 - >散列函数。
维基百科提供的哈希表的非常全面的描述 。
哈希表将不必每个元素的哈希进行比较。 它会根据密钥计算哈希码。 例如,如果键是4,则散列码可以是 - 4 * X * Y。 现在指针清楚地知道挑哪个元素。
然而,如果它一直是一个数组,它必须通过整个数组遍历来搜索这个元素。
为什么是[它]为[散列表执行由关键查找比阵列更好(VS为O(n O(1)))]? 我的意思是:我有钥匙,我哈希它..我有散..不应该的算法比较对每一个元素的hash该哈希? 我觉得有内存配置背后的一些伎俩,不是吗?
一旦你的哈希值,它可以让你斗的阵列中计算的“理想”或预期位置:常见:
理想的桶=散列%num_buckets
问题是,那么另一个值可能已经散列到桶中,在这种情况下,哈希表的实现主要有两个选择:
1)尝试另一个桶
2)让多个不同的值“属于”一个水桶,也许通过使桶容纳一个指针到值的链表
为了实现1,被称为开放地址或封闭的哈希 ,你跳来跳去其他区块:如果你发现你的价值,伟大的; 如果你发现一个从未使用的桶,那么你可以你的价值在那里,如果插入存储,或者你知道搜索时,你永远也找不到自己的价值。 有用于搜索比为O(n),如果您遍历替代性的桶的方式结束了同一个桶多次搜索还差潜力; 例如,如果你使用二次探测你试试理想斗指数+1,然后+4,然后+9,然后+16等等-但你必须避免使用如出界外区存取% num_buckets
,所以如果有说12桶然后理想+ 4和理想+ 16查询的同一个桶。 它可以是昂贵跟踪哪个桶已被搜索,所以它可能很难知道何时放弃过:它的实现可以乐观,并认为它总能找到任何值或者未使用的桶(冒着永远纺),它可以有一个计数器和尝试的阈值后要么放弃或发起一个线性斗逐桶搜索。
为了实现2,如已知的封闭寻址或分离链 ,必须值的容器/数据结构,所有散列以理想桶内搜索。 如何高效,这是取决于所使用的容器的类型。 它的普遍预期,元件中的一个水桶碰撞的数量会很小,这与非对抗性输入一个好的哈希函数的真实,典型真够即使是普通的散列函数特别是桶的质数。 因此,一个链表或连续阵列经常使用,尽管为O(n)的搜索属性:链表是简单的实施和操作上,并且阵列一起打包的数据更好存储器高速缓存局部性和存取速度。 最坏的可能情况是,虽然在表中的每个值散列到同一桶中,并在该桶容器现在拥有的所有值:整个哈希表,然后只桶的容器一样高效。 一些Java哈希表的实现已经开始使用二叉树如果散列到同一桶元素的数量超过阈值,以确保复杂决不会比O(log2n)差。
蟒散列的1 =开放寻址=一例封闭散列。 C ++ std::unordered_set
是关闭寻址=分离链的一个例子。
我想你回答了你自己的问题在那里。 “不应该的算法比较对每一个元素的hash该哈希”。 这是什么样的它,当它不知道你要搜索的内容索引位置。 它比较每个元素找到你要找的人:
例如,假设你正在寻找所谓的“汽车”的字符串数组内的项目。 你需要去通过每一个项目,并检查item.Hash()==“汽车” .Hash()来发现,那就是你要找的项目。 显然一直在寻找,当它不使用哈希,但例如站立。 那么你有一个哈希表。 什么一个哈希表的作用是它创建了一个稀疏阵列,或有时阵列桶的上述的人。 然后,它使用“驾驶” .Hash()来推断出那稀疏数组中的“Car”项目实际上是。 这意味着,它没有在整个阵列搜索找到你的项目。