将列表拆分成多个列表以获得加速?

时间:2011-08-11 11:16:00

标签: python performance list nested-lists

假设我的列表长约1,000,000个条目。要获得一个项目,时间将是O(500,000),这对我来说似乎很长。

将列表拆分为多个列表时会发生什么?我们来看一个例子:
将列表拆分为10个部分,我有一个列表如下:

splitted_list = [
    [list with 100,000 entries],
    [list with 100,000 entries],
    [list with 100,000 entries],
    [list with 100,000 entries],
    [list with 100,000 entries],
    [list with 100,000 entries],
    [list with 100,000 entries],
    [list with 100,000 entries],
    [list with 100,000 entries],
    [list with 100,000 entries]
]

获得一个项目的时间是O(5) + O(50,000) = O(50,005),并且加速率大约为1000%!

当拆分原始列表关于它的根,在这种情况下是1000时,这将给我们一个包含1000个列表的列表,其中包含另外1000个条目。

splitted_list = [
    [list with 1000 entries],
    [list with 1000 entries],
    [list with 1000 entries],
    [list with 1000 entries],
    ...
]

现在看一下获取项目的时间:

O(500) + O(500) = O(1000)
O(1000) < O(50,005) < O(500,000)

这是最佳加速约1000倍!我认为难以置信,所以我的问题是:

这是否也适用于实践,或者这只是理论吗?

3 个答案:

答案 0 :(得分:5)

从列表is O(1)中按索引获取项目,无论列表大小如何。

答案 1 :(得分:4)

你的问题的答案是你正在考虑linked lists,其中每个元素都有一个指向下一个元素的指针。这些都有O(n)索引,因为获取第n个元素的唯一方法是从头开始遍历列表。

您的想法与各种数据结构有关,其中最接近的可能是skip list。这是一个基于链表的数据结构,但节点的“高速公路”可以跳过列表中的多个元素。优点是你可以在高速公路上跑到达列表的中间位置,然后在你需要单个元素精度时下拉到“较慢的通道”,给出O(log n)索引效率 - 与一个binary tree。当然,缺点是执行其他链表操作(如随机插入)会更复杂(也更慢)。

然而,Python列表是在动态增长arrays下实现的。它们具有O(1)索引,因为要获得第三个元素,您只需将三个(单位)添加到第一个元素的内存地址,而不必遍历其间的所有元素。

您可能对Wikipedia article on data structures感兴趣。

答案 2 :(得分:3)

我假设您正在谈论在列表中查找元素。

如果你正在谈论将一个已排序的列表分成多个排序列表并指向他们的头部,恭喜你,你几乎已经发现了B树。

如果这些列表确实是数组(即你有恒定时间随机访问),你也可以进行二进制搜索。