- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我们知道tuple
对象是不可变的,因此是散列的。我们还知道lists
是可变的和不可散列的。
这很容易说明
>>> set([1, 2, 3, (4, 2), (2, 4)])
{(2, 4), (4, 2), 1, 2, 3}
>>> set([1, 2, 3, [4, 2], [2, 4]])
TypeError: unhashable type: 'list'
hash
的含义是什么,如果为了检查唯一性(例如,在构建集合时),我们仍然必须检查集合中的任何iterable中的每个单独项?
hash
值,但仍然是不同的。因此,
hash
仅用于比较对象是不够的。那么,散列的意义是什么?为什么不直接检查iterables中的每个项目呢?
hash
只是一个(很快)的初步比较。如果
hashes
不同,我们知道对象是不同的。
最佳答案
现在,hash在这个上下文中的意义是什么,如果,为了检查唯一性(例如,在构建集合时),我们仍然必须检查集合中的任何iterable中的每个单独项?
是的,但是哈希用于两个对象可以相等的情况下进行保守估计,也用于分配一个“桶”到一个项目。如果哈希函数是精心设计的,那么很可能(不确定),大多数,如果不是全部,最终在不同的桶,因此,因此,我们使成员检查/插入/删除/…算法平均运行在恒定时间O(1),而不是O(n),这是典型的列表。
所以,你的第一个答案是部分正确的,尽管你必须考虑到桶肯定会提高性能,而且实际上比保守检查更重要。
背景
注:我将在这里使用一个简化的模型,使原理清晰,实际上字典的实现更为复杂。例如散列在这里只是一些数字,显示了普林西比。
哈希集和字典被实现为一个“bucket”数组。元素的散列决定了我们将元素存储在哪个bucket中。如果元素的数量增加,那么bucket的数量就会增加,字典中已经存在的元素通常会被“重新分配”到bucket中。
例如,空字典在内部可能看起来像:
+---+
| |
| o----> NULL
| |
+---+
| |
| o----> NULL
| |
+---+
'a'
,那么散列就是
123
。让我们考虑一个简单的算法,将一个元素分配给一个桶,这里有两个桶,所以我们会给元素分配一个偶数散列给第一个桶,而一个奇数散列给第二个桶。由于
'a'
的散列是奇数,因此我们将
'a'
分配给第二个bucket:
+---+
| |
| o----> NULL
| |
+---+
| | +---+---+
| o---->| o | o----> NULL
| | +-|-+---+
+---+ 'a'
'b'
是否是字典的成员,我们首先计算
hash('b')
,也就是
456
,因此如果我们把它添加到字典中,它将在第一个bucket中。因为第一个bucket是空的,所以我们不必在第二个bucket中寻找元素来确定
'b'
不是成员。
'c'
是否是一个成员,我们首先生成
'c'
的散列,即
789
,因此我们再次将其添加到第二个bucket,例如:
+---+
| |
| o----> NULL
| |
+---+
| | +---+---+ +---+---+
| o---->| o | o---->| o | o----> NULL
| | +-|-+---+ +-|-+---+
+---+ 'c' 'a'
'b'
是否是一个成员,我们将查看第一个bucket,然后,我们再也不必遍历
'c'
和
'a'
来确定
'b'
不是字典的成员。
'e'
和
'g'
(这里我们认为这些字符有一个奇怪的散列),那么这个bucket将非常满,因此如果我们稍后检查
'i'
是否是成员,我们仍然需要遍历元素。但是,如果元素的数量增加,通常存储桶的数量也会增加,并且字典中的元素将被分配一个新的存储桶。
'd'
添加到字典中,字典可能会注意到插入后的元素数
3
大于桶的数量
2
,因此我们创建了一个新的桶数组:
+---+
| |
| o----> NULL
| |
+---+
| |
| o----> NULL
| |
+---+
| |
| o----> NULL
| |
+---+
| |
| o----> NULL
| |
+---+
'a'
和
'c'
。现在所有具有哈希< cc> >
h
的元素将被分配给第一个桶,
h % 4 == 0
到第二个桶,
h % 4 == 1
到第三个桶,并且
h % 4 == 2
到最后一个桶。这意味着hash
h % 4 == 3
的
'a'
将存储在最后一个bucket中,hash
123
的
'c'
将存储在第二个bucket中,因此:
+---+
| |
| o----> NULL
| |
+---+
| | +---+---+
| o---->| o | o----> NULL
| | +-|-+---+
+---+ 'c'
| |
| o----> NULL
| |
+---+
| | +---+---+
| o---->| o | o----> NULL
| | +-|-+---+
+---+ 'a'
789
的
'b'
添加到第一个bucket中,这样:
+---+
| | +---+---+
| o---->| o | o----> NULL
| | +-|-+---+
+---+ 'b'
| | +---+---+
| o---->| o | o----> NULL
| | +-|-+---+
+---+ 'c'
| |
| o----> NULL
| |
+---+
| | +---+---+
| o---->| o | o----> NULL
| | +-|-+---+
+---+ 'a'
456
或
'a'
,也会发生同样的情况(但是使用不同的桶),如果我们寻找
'a'
(这里用哈希
'b'
),那么我们将在第三个桶中进行搜索,并且永远不必检查单个元素的相等性,以知道它不是字典的一部分。
'c'
是否是一个成员,那么我们计算
'd'
的散列(这里是
12
),并在第二个bucket中搜索。因为bucket不是空的,所以我们开始遍历它。
'e'
在字典中。
'e'
等于< > >,因为事实并非如此,我们知道
345
和< >是不一样的。如果比较这两个对象比较昂贵,那么我们可以节省一些周期。
关于python - 如果我们仍然需要检查每个项目,哈希的含义是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53160472/
这个问题在这里已经有了答案: Towards the "true" definition of JAVA_HOME (5 个答案) 关闭 4 年前。 为什么 ActiveMQ 提供者需要设置 JAV
这个问题在这里已经有了答案: What is a lambda expression in C++11? (10 个答案) 关闭 8 年前。 这是来自 boosts asio 的一个例子。这是什么意
这个问题在这里已经有了答案: What does the double colon (::) mean in CSS? (3 个答案) 关闭 7 年前。 我经常看到这种用法。特别是伪类。“::”在
嗨,另一个愚蠢的简单问题。我注意到在Apple框架中的某些typedef中使用符号"<<"谁能告诉我这是什么意思?: enum { UIViewAutoresizingNone
someObject.$() 是什么意思? 我正在浏览 sapui5 工具包中的 tilecontainer-dbg 文件,发现了这个: var oDomRef = this.$(); or some
这个问题已经有答案了: How to interpret function parameters in software and language documentation? (4 个回答) 已关闭
我遇到过这个语法。任何人都可以解释一下 getArg1ListInfo:()=>(object.freeze(arg1)) 的含义 function foo (arg1,arg2) { let
对于子类,我有以下代码: class child1 : public parent { public: static parent* function1(void) { ret
这个问题在这里已经有了答案: What does "|=" mean? (pipe equal operator) (6 个答案) 关闭 1 年前。 我有一部分代码包含以下功能: void Keyb
以下在 C++ 中是什么意思? typedef PComplex RComplex [100]; 请注意,PComplex 是我代码中的用户定义类型。 谢谢 最佳答案 RComplex 是 PComp
在我的 Lisp 代码中,我有函数 (nfa-regex-compile),它创建一个包含初始状态、转换和最终状态的 cons 列表(表示自动机的节点)从作为参数给出的正则表达式开始。 在这种情况下,
以下文字摘自 Learning Spark 第 3 章 One issue to watch out for when passing functions is inadvertently seria
PHP 文档 block 中以下内容的含义是什么: #@+ zend框架代码中的一个例子: /**#@+ * @const string Version constant numbers */ c
由于 python 的一些版本控制问题,我必须使用自定义函数来比较 HMAC (SHA512)。为此,我找到了这个函数: def compare_digest(x, y): if not (i
取自this answer here : static const qi::rule node = '{' >> *node >> '}' | +~qi::char_("{}"); 请注意,声明了名称
我正在查看 chi 包的文档。我看到类似的东西: https://github.com/pressly/chi/blob/master/_examples/rest/main.go#L154 data
我想知道如果我采用值为 8 的 INT,这是否意味着我只能从 1 到 99999999 或从 1 到 4294967295 UNSIGNED? 最佳答案 文档似乎很清楚这一点: Numeric Typ
我想知道如果我采用值为 8 的 INT,这是否意味着我只能从 1 到 99999999 或从 1 到 4294967295 UNSIGNED? 最佳答案 文档似乎很清楚这一点: Numeric Typ
这个问题在这里已经有了答案: 关闭9年前。 Possible Duplicate: Does “/* (non-javadoc)” have a well-understood meaning? 以下
在 Prolog 代码中,可以使用“ headless ”Horn 子句将指令传递给编译器,这些子句与指向左侧的物质蕴涵 ':-' (⇐) 的左侧没有头部关系。例如,导入模块或声明 Unit Test
我是一名优秀的程序员,十分优秀!