python wiki说:“使用集合和词典进行成员资格测试比搜索序列O(n)快得多,O(n)。当测试”a in b“时,b应该是一个集合或字典而不是列表或元组。“
每当速度在我的代码中很重要时,我一直在使用集合代替列表,但最近我一直想知道为什么集合比列表快得多。任何人都可以解释,或者指出一个可以解释的消息来源,在python的幕后发生了什么,以便更快地创建集合?
答案 0 :(得分:74)
list
:想象一下,你在衣柜里寻找你的袜子,但你不知道你的袜子在哪个抽屉里,所以你必须抽屉抽屉直到你找到他们(或许你永远不会)。这就是我们所说的O(n)
,因为在最糟糕的情况下,您会查看所有抽屉(其中n
是抽屉的数量)。
set
:现在,想象一下你仍然在衣橱里寻找你的袜子,但现在你知道你的袜子在哪个抽屉里,比如在第三个抽屉里。因此,您只需在第三个抽屉中搜索,而不是在所有抽屉中搜索。这就是我们所说的O(1)
,因为在最糟糕的情况下,你只会看到一个抽屉。
答案 1 :(得分:46)
使用hash tables实现集合。无论何时向对象添加对象,都会使用要添加的对象的哈希来确定set
对象的内存中的位置。在测试成员资格时,所有需要完成的工作基本上是查看对象是否位于由其哈希确定的位置,因此此操作的速度不依赖于集合的大小。相反,对于列表,需要搜索整个列表,随着列表的增长,列表将变慢。
这也是集合不保留您添加的对象顺序的原因。
请注意,集合通常不比列表快 - 对于集合,成员资格测试更快,因此删除元素也是如此。只要您不需要这些操作,列表通常会更快。
答案 2 :(得分:6)
我认为你需要好好看一本关于数据结构的书。基本上,Python列表实现为dynamic arrays,集合实现为hash tables。
这些数据结构的实现赋予它们完全不同的特征。例如,哈希表的查找时间非常快,但无法保留插入顺序。
答案 3 :(得分:4)
list
:假设您正在寻找笔,但是您不知道笔在哪个抽屉中,因此您必须逐个抽屉地搜索抽屉,直到找到它为止(或者可能永远不会找到)。这就是我们所说的O(n),因为在最坏的情况下,您将查看所有抽屉(其中n是抽屉数)。
set
:现在,假设您还在寻找笔,但是现在您知道笔在哪个抽屉中,例如在第8个抽屉中。因此,您将只在第8个抽屉中搜索,而不是在所有抽屉中搜索。这就是我们所说的O(1),因为在最坏的情况下,您只会看到一个抽屉。
基本上,Python 列表被实现为dynamic arrays
,而集合被实现为hash tables
。
答案 4 :(得分:2)
Python使用hashtables,它有O(1)查找。
答案 5 :(得分:2)
虽然到目前为止我还没有测量过任何与python相关的性能,但我仍然想指出列表通常更快。
是的,你有O(1)对O(n)。但请记住,这只会提供有关某些事物的渐近行为的信息。这意味着如果你的n非常高,O(1)总是会更快 - 理论上。实际上,n通常需要比通常的数据集大得多。
所以集合本身并不比列表快,但只有当你必须处理很多元素时才会这样。
答案 6 :(得分:0)
必须逐个搜索列表,其中集合或字典具有快速搜索的索引。
答案 7 :(得分:0)
基本上,取决于您正在执行的操作...
*要添加元素,则集不需要移动任何数据,而要做的就是计算一个哈希值并将其添加到表中。对于列表插入,则可能有要移动的数据。
*要删除元素-集合所需要做的就是从哈希表中删除哈希条目,对于列表,它可能需要移动数据(平均为数据的1/2。
*对于搜索(即in运算符)-一组只需要计算数据项的哈希值,请在哈希表中找到该哈希值(如果存在)-然后是bingo。对于列表,搜索必须依次查找每个项目-平均列表中所有术语的1/2。甚至对于成千上万的项目,一组搜索都将更快。
答案 8 :(得分:0)
实际上,在每种情况下,集合都不比列表快。通常列表是速度而不是集合。 但是在搜索集合中的元素的情况下,它是速度,因为集合是使用哈希表实现的。所以基本上它不必搜索完整的集合,所以平均时间复杂度是 O(1)。列表使用动态数组,它应该在完整数组中查找以进行搜索。所以它需要 O(n)。 n 是列表的大小。
所以最后我们可以看到在某些情况下集合更好,而列表在某些情况下更好。由我们根据我们的任务选择合适的数据结构。