是什么使集合比列表更快?


70

python Wiki说:“使用集和字典进行成员资格测试比搜索序列O(n)更快,O(1)。测试“ a in b”时,b应该是集合或字典,而不是列表或元组。”

每当速度在我的代码中很重要时,我就一直使用集代替列表,但是最近我一直在想为什么集比列表快得多。任何人都可以解释一下,或者让我指向可以解释这一点的消息源,这是为了在python中更快地进行设置吗?



Answers:


104

集是使用哈希表实现的。每当您将对象添加到集合中时,该对象在内存中的位置set的哈希来确定对象。在测试成员资格时,基本上需要做的只是查看对象是否在其哈希确定的位置,因此此操作的速度不取决于集合的大小。相反,对于列表,需要搜索整个列表,随着列表的增长,列表的搜索速度会变慢。

这也是集合不保留您添加的对象顺序的原因。

请注意,集合通常不会比列表快—成员资格测试对于集合来说更快,因此删除元素也是如此。只要您不需要这些操作,列表通常就会更快。


163

list:假设您要在壁橱中寻找袜子,但是您不知道袜子在哪个抽屉里,因此您必须逐个抽屉地搜索袜子,直到找到它们为止(或者也许永远不会找到)。这就是我们所说的O(n),因为在最坏的情况下,您将查看所有抽屉(这里n是抽屉数)。

set:现在,想象您还在壁橱里寻找袜子,但是现在您知道了袜子在哪个抽屉里,比如说在第三个抽屉里。因此,您将只在第三个抽屉中搜索,而不是在所有抽屉中搜索。这就是我们所说的O(1),因为在最坏的情况下,您只会看到一个抽屉。


3
使用实时示例是理解或教导任何事物的最佳方法。做得好!
Workonphp

@juliomalegria袜子抽屉是否代表元素的list/set或存储位置中的元素?
AlexG

那么,为什么我们“知道袜子在第三个抽屉中”的原因使得要查询的值被散列,因此我们可以直接转到相应的内存位置以查找数据?
AlexG

这是解决该问题的完美ELI5!
AK47

1
多么生动,简洁的示例说明了big-O和哈希值的价值!荣誉
kghastie

10

我认为您需要仔细阅读一本有关数据结构的书。基本上,Python列表被实现为动态数组,而集合被实现为哈希表

这些数据结构的实现赋予它们根本不同的特征。例如,哈希表的查找时间非常快,但无法保留插入顺序。


很抱歉,无法恢复旧线程。但是对书有什么建议吗?
Anakhand

4

list:想象您正在寻找笔,但是您不知道笔在哪个抽屉中,因此您必须逐个抽屉地搜索抽屉,直到找到它为止(或者可能永远不会)。这就是我们所说的O(n),因为在最坏的情况下,您将查看所有抽屉(其中n是抽屉数)。

set:现在,想象您还在寻找笔,但是现在您知道笔在哪个抽屉中,例如在第8个抽屉中。因此,您将只在第8个抽屉中搜索,而不是在所有抽屉中搜索。这就是我们所说的O(1),因为在最坏的情况下,您只会看到一个抽屉。

基本上,Python列表实现为dynamic arrays集合集实现为hash tables



3

尽管到目前为止,我还没有测量过与python相关的任何性能,但我仍然想指出,列表通常更快。

是的,您有O(1)对O(n)。但是请始终记住,这仅提供有关某些事物的渐近行为的信息。这意味着,如果您的n很高,则O(1)总是会更快-从理论上讲。但是实际上,n通常需要比通常的数据集大得多。

因此,集合本身并不比列表本身快,而仅在必须处理许多元素时才如此。


1

基本上,取决于您正在执行的操作...

*对于添加元素-集合不需要移动任何数据,它所需要做的就是计算一个哈希值并将其添加到表中。对于列表插入,则可能有要移动的数据。

*要删除元素-集合所需要做的就是从哈希表中删除哈希条目,对于列表而言,它可能需要移动数据(平均为数据的1/2)。

*对于搜索(即in运算符)-一组只需要计算数据项的哈希值,请在哈希表中找到该哈希值,如果存在-则使用bingo。对于列表,搜索必须依次查找每个项目-平均列表中所有术语的1/2。即使对于成千上万的项目,一组搜索也将更快。


0

列表必须一个一个地搜索,其中一个集合或字典都有一个索引,以加快搜索速度。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.