就哈希函数而言,桶是什么?
What are buckets in terms of hash functions?
看书 Mining of Massive Datasets,第 1.3.2 节概述了哈希函数。没有计算机科学背景,这对我来说很陌生; Ruby 是我的第一语言,其中 hash
似乎等同于 Dictionary<object, object>
。而且我从来没有考虑过如何这种数据结构。
本书提到 散列函数,作为实现这些字典数据结构的一种方式。本段:
First, a hash function h takes a hash-key value as an argument and produces
a bucket number as a result. The bucket number is an integer, normally in the
range 0 to B − 1, where B is the number of buckets. Hash-keys can be of any
type. There is an intuitive property of hash functions that they “randomize”
hash-keys
hash function
中的桶到底是什么?听起来桶是 array-like
结构,而 hash function
是某种算法/array-like-structure
搜索,每次都会产生相同的桶号?这个比喻性的桶里面是什么?
我一直读到 javascript objects/ruby 哈希等不能保证顺序。在实践中我发现键的顺序没有改变(实际上,我认为使用旧版本的 Mozilla 的 Rhino 解释器 JS 对象顺序 DID 改变了,但我不能确定......)。
这是否意味着散列 (Ruby) / 对象 (JS) 未被这些 hash functions
解析?
hashing
这个词是否会根据您使用计算机的水平而有不同的含义?也就是说,Ruby 散列似乎与 C++ 散列不同...
当您散列一个值时,任何有用的散列函数 通常 具有比 域[=] 更小的 范围 30=]。这意味着在一个大的输入值列表(例如所有可能的字母组合)中,它将输出任何一个较小的值列表(一个以特定长度为上限的数字)。这意味着不止一个输入值可以映射到相同的输出值。
在这种情况下,输出值称为桶。
考虑函数 f(x) = x mod 2
这会生成以下输出;
1 => 1
2 => 0
3 => 1
4 => 0
在这种情况下,有两个桶(1 和 0),每个桶中都有一堆输入值。
一个好的散列函数将平等地填充所有这些 'buckets',从而实现更快的搜索等。如果你采用任何数字的 mod,你就会得到要查看的桶,并且因此必须搜索比最初搜索更少的结果,因为每个桶中的结果少于整个输入集。在理想情况下,哈希计算速度很快,每个桶中只有一个结果,这使得查找只需应用哈希函数所需的时间。
这当然是一个简化的例子,但希望你明白了吗?
散列函数的概念总是一样的。它是一个计算一些数字来表示一个对象的函数。这个号码的属性应该是:
- 计算起来相对便宜
- 所有对象都尽可能不同。
让我们举一个真实的例子来说明我的意思,通常使用 why/how 哈希。
取所有自然数。现在让我们假设检查 2 个数字是否相等是很昂贵的。
我们也定义一个相对便宜的散列函数如下:
hash = number % 10
思路很简单,取数字的最后一位作为hash即可。在您得到的解释中,这意味着我们将所有以 1 结尾的数字放入一个假想的 1 桶中,将所有以 2 结尾的数字放入 2 桶中,依此类推...
那些桶并不真正作为数据结构存在。它们只是让哈希函数的推理变得容易。
现在我们有了这个便宜的哈希函数,我们可以用它来降低其他事情的成本。例如,我们想创建一个新的数据结构来实现廉价的数字搜索。我们称此数据结构为哈希图。
这里其实我们把所有带hash=1
的数字放在一个list/set/...里,我们把带hash=5
的数字放到自己的list/set里。 ..等等
如果我们想查找一些数字,我们首先计算它的哈希值。然后我们检查这个hash对应的list/set,然后只比较"similar"个数来找到我们想要的确切数。这意味着我们只需要做一个廉价的哈希计算,然后用昂贵的相等性检查来检查 1/10 的数字。
注意这里我们使用散列函数来定义一个新的数据结构。哈希本身不是数据结构。
考虑 phone 一本书。
假设您想在 phone 书中寻找唐老鸭。
必须查看每个页面以及该页面上的每个条目,效率非常低。因此,我们没有这样做,而是做了以下事情:
我们创建一个索引
我们创建了一种从名称中获取索引键的方法
对于 phone 一本书,索引从 A-Z 开始,用于获取索引键的函数只是获取姓氏的第一个字母。
在这种情况下,哈希函数采用 Donald Duck
并为您提供 D
。
然后你取 D
并转到所有姓氏以 D 开头的人所在的索引。
这样说太简单了。
我简单解释一下。在使用链接技术(开放式散列或封闭式寻址)处理冲突时,桶进入画面
这里,每个数组条目应对应一个桶,每个数组条目(如果非空)将有一个指向链表头部的指针。 (桶是用链表实现的)
散列table 应使用散列函数来计算存储桶数组的索引,从中可以找到所需的值。
也就是说,在检查某个元素是否在散列 table 中时,首先对键进行散列以找到要查看的正确存储桶。然后遍历对应的链表,定位到想要的元素。
类似地,在任何元素添加或删除时,散列用于找到合适的桶。然后在桶中查找presence/absence个需要的元素,据此从桶中遍历相应的链表added/removed
。
看书 Mining of Massive Datasets,第 1.3.2 节概述了哈希函数。没有计算机科学背景,这对我来说很陌生; Ruby 是我的第一语言,其中 hash
似乎等同于 Dictionary<object, object>
。而且我从来没有考虑过如何这种数据结构。
本书提到 散列函数,作为实现这些字典数据结构的一种方式。本段:
First, a hash function h takes a hash-key value as an argument and produces a bucket number as a result. The bucket number is an integer, normally in the range 0 to B − 1, where B is the number of buckets. Hash-keys can be of any type. There is an intuitive property of hash functions that they “randomize” hash-keys
hash function
中的桶到底是什么?听起来桶是 array-like
结构,而 hash function
是某种算法/array-like-structure
搜索,每次都会产生相同的桶号?这个比喻性的桶里面是什么?
我一直读到 javascript objects/ruby 哈希等不能保证顺序。在实践中我发现键的顺序没有改变(实际上,我认为使用旧版本的 Mozilla 的 Rhino 解释器 JS 对象顺序 DID 改变了,但我不能确定......)。
这是否意味着散列 (Ruby) / 对象 (JS) 未被这些 hash functions
解析?
hashing
这个词是否会根据您使用计算机的水平而有不同的含义?也就是说,Ruby 散列似乎与 C++ 散列不同...
当您散列一个值时,任何有用的散列函数 通常 具有比 域[=] 更小的 范围 30=]。这意味着在一个大的输入值列表(例如所有可能的字母组合)中,它将输出任何一个较小的值列表(一个以特定长度为上限的数字)。这意味着不止一个输入值可以映射到相同的输出值。
在这种情况下,输出值称为桶。
考虑函数 f(x) = x mod 2
这会生成以下输出;
1 => 1
2 => 0
3 => 1
4 => 0
在这种情况下,有两个桶(1 和 0),每个桶中都有一堆输入值。
一个好的散列函数将平等地填充所有这些 'buckets',从而实现更快的搜索等。如果你采用任何数字的 mod,你就会得到要查看的桶,并且因此必须搜索比最初搜索更少的结果,因为每个桶中的结果少于整个输入集。在理想情况下,哈希计算速度很快,每个桶中只有一个结果,这使得查找只需应用哈希函数所需的时间。
这当然是一个简化的例子,但希望你明白了吗?
散列函数的概念总是一样的。它是一个计算一些数字来表示一个对象的函数。这个号码的属性应该是:
- 计算起来相对便宜
- 所有对象都尽可能不同。
让我们举一个真实的例子来说明我的意思,通常使用 why/how 哈希。
取所有自然数。现在让我们假设检查 2 个数字是否相等是很昂贵的。
我们也定义一个相对便宜的散列函数如下:
hash = number % 10
思路很简单,取数字的最后一位作为hash即可。在您得到的解释中,这意味着我们将所有以 1 结尾的数字放入一个假想的 1 桶中,将所有以 2 结尾的数字放入 2 桶中,依此类推...
那些桶并不真正作为数据结构存在。它们只是让哈希函数的推理变得容易。
现在我们有了这个便宜的哈希函数,我们可以用它来降低其他事情的成本。例如,我们想创建一个新的数据结构来实现廉价的数字搜索。我们称此数据结构为哈希图。
这里其实我们把所有带hash=1
的数字放在一个list/set/...里,我们把带hash=5
的数字放到自己的list/set里。 ..等等
如果我们想查找一些数字,我们首先计算它的哈希值。然后我们检查这个hash对应的list/set,然后只比较"similar"个数来找到我们想要的确切数。这意味着我们只需要做一个廉价的哈希计算,然后用昂贵的相等性检查来检查 1/10 的数字。
注意这里我们使用散列函数来定义一个新的数据结构。哈希本身不是数据结构。
考虑 phone 一本书。
假设您想在 phone 书中寻找唐老鸭。
必须查看每个页面以及该页面上的每个条目,效率非常低。因此,我们没有这样做,而是做了以下事情:
我们创建一个索引
我们创建了一种从名称中获取索引键的方法
对于 phone 一本书,索引从 A-Z 开始,用于获取索引键的函数只是获取姓氏的第一个字母。
在这种情况下,哈希函数采用 Donald Duck
并为您提供 D
。
然后你取 D
并转到所有姓氏以 D 开头的人所在的索引。
这样说太简单了。
我简单解释一下。在使用链接技术(开放式散列或封闭式寻址)处理冲突时,桶进入画面
这里,每个数组条目应对应一个桶,每个数组条目(如果非空)将有一个指向链表头部的指针。 (桶是用链表实现的)
散列table 应使用散列函数来计算存储桶数组的索引,从中可以找到所需的值。
也就是说,在检查某个元素是否在散列 table 中时,首先对键进行散列以找到要查看的正确存储桶。然后遍历对应的链表,定位到想要的元素。
类似地,在任何元素添加或删除时,散列用于找到合适的桶。然后在桶中查找presence/absence个需要的元素,据此从桶中遍历相应的链表added/removed
。