python是否有排序列表?


128

我所说的结构是:

  • x.push()操作复杂度O(log n)
  • O(log n)查找元素的复杂度
  • O(n)复杂度进行计算list(x)将被排序

我也有一个有关性能的相关问题list(...).insert(...),现在在这里


memcpy仍然是O(n)运算。我不确定Python如何精确实现列表,但是我敢打赌,它们存储在连续内存中(肯定不是链接列表)。如果确实如此,则bisect您演示使用的插入将具有复杂度O(n)
Stephan202

2
可悲的是没有开箱。但是Grant Jenk的sortedcontainers库非常出色。stackoverflow.com/a/22616929/284795
恐慌上校

Answers:


52

标准Python列表不以任何形式排序。标准的heapq模块可用于将O(log n)追加到现有列表中,并删除O(log n)中最小的模块,但在定义中不是排序列表。

有许多符合您需求的Python平衡树实现,例如rbtreeRBTreepyavl


1
+1 rbtree,它工作得很好(但包含本地代码;没有纯Python,不是那么容易的也许部署)
威尔

12
sortedcontainers是纯Python和Fast-as-C(如rbtree),具有性能比较。
GrantJ 2014年

“在您的定义中不是排序列表。” 为何如此?
上校恐慌

4
heapq只允许找到最小的元素;OP要求的结构可以在O(log n)中找到任何元素,而堆没有。
Martin v。Löwis2015年

70

您的big-O需求是否有特定原因?还是您只是想要它快?所述sortedcontainers模块是纯Python和快速(如在快速作为-C实现比如blist和rbtree)。

性能比较表明它与基准测试blist的排序列表类型更快或看齐。还要注意,rbtree,RBTree和PyAVL提供排序的dict和set类型,但没有排序的列表类型。

如果需要性能,请始终记住要进行基准测试。在它还显示基准比较之前,应该怀疑使用Big-O表示法证明快速的模块。

免责声明:我是Python sortedcontainers模块的作者。


安装:

pip install sortedcontainers

用法:

>>> from sortedcontainers import SortedList
>>> l = SortedList()
>>> l.update([0, 4, 1, 3, 2])
>>> l.index(3)
3
>>> l.add(5)
>>> l[-1]
5

4
的确,我将sortedcontainer与bisect 0.0845024989976进行了比较:SortedList.add()与0.596589182518bisect.insort(),因此速度相差7倍!而且我希望速度差距会随着列表的长度而增加,因为sortedcontainers插入排序在O(log n)中起作用,而bisect.insort()在O(n)中起作用。
2015年

1
@gaborous,因为bisect仍使用列表,因此插入仍然有效O(n)
njzk2

34

尽管我仍然从未检查过基本Python列表操作的“大O”速度,但bisect在这种情况下,标准模块可能也值得一提:

import bisect
L = [0, 100]

bisect.insort(L, 50)
bisect.insort(L, 20)
bisect.insort(L, 21)

print L
## [0, 20, 21, 50, 100]

i = bisect.bisect(L, 20)
print L[i-1], L[i]
## 20, 21

PS。啊,对不起,bisect在提到的问题中被提及。不过,我认为,如果此信息在这里,不会有太大危害)

PPS。而CPython的名单实际上是数组(不是,比方说,skiplists或等)。好吧,我想它们一定很简单,但就我而言,这个名称有点误导。


因此,如果我没记错的话,平分/列表速度可能是:

  • 对于push():在最坏的情况下为O(n);
  • 搜索:如果我们认为数组索引的速度为O(1),则搜索应为O(log(n))操作;
  • 用于创建列表:O(n)应该是列表复制的速度,否则为同一列表的O(1))

更新。在评论中进行讨论之后,让我在这里链接这些SO问题:如何实现Python的列表以及什么是Python列表函数的运行时复杂性


因为列表已经排序,push()应该在O(log n)中。
estani

1
也许我应该说“插入操作”。无论如何,那是大约一年前的事,所以现在我可以轻松地将事情弄混或错过一些事情
2012年

您始终可以将值插入O(log n)中的排序列表中,请参阅二进制搜索。push()被定义为插入操作。
estani 2012年

2
真正。但是,尽管找到插入位置确实需要O(log n)操作,但实际的插入操作(即将元素添加到数据结构中)可能取决于该结构(请考虑将元素插入已排序的数组中)。而且由于Python列表实际上是数组,因此可能需要O(n)。由于评论的大小限制,我将从答案文本中链接两个相关的SO问题(请参见上文)。
ジョージ

好理由。我不知道列表在Python中作为数组处理的位置。
estani 2012年

7
import bisect

class sortedlist(list):
    '''just a list but with an insort (insert into sorted position)'''
    def insort(self, x):
        bisect.insort(self, x)

bisect.insort()中的隐含insert()为O(n)
j314erre

6

尽管(尚未)提供自定义搜索功能,但该heapq模块可能适合您的需求。它使用常规列表实现堆队列。您必须编写自己的有效成员资格测试,该测试利用队列的内部结构(可以在O(log n)中完成,我想说...)。有一个缺点:提取排序列表的复杂度为O(n log n)


很好,但是很难一分为二。
ilya n。

3
堆中如何进行O(log n)成员资格测试?如果要查找值x,如果发现大于x的值,则可以停止向下查找分支,但是对于x的随机值,很有可能出现叶子的50%,并且可能无法修剪太多。
市场

1

我会使用biscectsortedcontainers模块。我确实没有经验,但是我认为该heapq模块有效。它包含一个Heap Queue


0

在Python上实现您自己的排序列表可能并不困难。以下是概念证明:

import bisect

class sortlist:
    def __init__(self, list):
        self.list = list
        self.sort()
    def sort(self):
        l = []
        for i in range(len(self.list)):
            bisect.insort(l, self.list[i])
        self.list = l
        self.len = i
    def insert(self, value):
        bisect.insort(self.list, value)
        self.len += 1
    def show(self):
        print self.list
    def search(self,value):
        left = bisect.bisect_left(self.list, value)
        if abs(self.list[min([left,self.len-1])] - value) >= abs(self.list[left-1] - value):
            return self.list[left-1]
        else:
            return self.list[left]

list = [101, 3, 10, 14, 23, 86, 44, 45, 45, 50, 66, 95, 17, 77, 79, 84, 85, 91, 73]
slist = sortlist(list)
slist.show()
slist.insert(99)
slist.show()
print slist.search(100000000)
print slist.search(0)
print slist.search(56.7)

=========结果============

[3、10、14、17、23、44、45、45、50、66、73、77、79、84、85、86、91、95、101]

[3、10、14、17、23、44、45、45、50、66、73、77、79、84、85、86、91、95、99、101]

101

3

50

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.