Python 用于双端排序列表的最佳数据结构

Python 用于双端排序列表的最佳数据结构,python,performance,algorithm,data-structures,collections,Python,Performance,Algorithm,Data Structures,Collections,我需要一个可以执行以下操作的集合数据结构: 分类 允许我快速弹出列表O(日志n)前后的值 插入新值后保持排序 允许使用用户指定的比较函数,因为我将存储元组并希望对特定值进行排序 不需要螺纹安全 可选地允许高效的haskey()查找(不过我很乐意为此维护一个单独的哈希表) 我在这个阶段的想法是,我需要一个优先级队列和一个哈希表,尽管我不知道是否可以快速地从优先级队列的两端弹出值。另一种可能是简单地维护OrderedDictionary,并在每次添加更多数据时对其进行插入排序 因为我对中等数量的

我需要一个可以执行以下操作的集合数据结构:

  • 分类
  • 允许我快速弹出列表O(日志n)前后的值
  • 插入新值后保持排序
  • 允许使用用户指定的比较函数,因为我将存储元组并希望对特定值进行排序
  • 不需要螺纹安全
  • 可选地允许高效的haskey()查找(不过我很乐意为此维护一个单独的哈希表)
我在这个阶段的想法是,我需要一个优先级队列和一个哈希表,尽管我不知道是否可以快速地从优先级队列的两端弹出值。另一种可能是简单地维护OrderedDictionary,并在每次添加更多数据时对其进行插入排序

因为我对中等数量的项目的性能感兴趣(我估计不到200000),所以我不确定这些操作需要什么渐近性能。n不会无限增长,因此
k*O(n)
中的低恒定性能
k
可能同样重要
O(n)
。也就是说,我希望插入和弹出操作都需要
O(logn)
时间


此外,Python中是否有任何特定的实现?我真的不想自己写这段代码。

如果这是Java,我会使用带有NavigableSet接口的树集


这是以红黑树的形式实现的。

使用或数据库(如stdlib中的)可能会获得此类操作的良好性能。

我建议使用某种平衡的二叉树,如红黑树

A抛出了几个实现。在谷歌上搜索会给你更多

在PyPi上看起来非常完整,同时有Python和C/Cython实现。我还没有用过它,所以请注意清空

红黑树保持排序,大多数操作(插入、删除、查找)都是O(log2(N)),因此在包含200000个条目的树中查找元素平均需要17-18次比较。

听起来像是A可以满足您的所有要求。它基本上是一个动态大小的排序链表,带有O(logn)插入和删除

我不太懂Python,但这个链接似乎很相关:


我想您需要对它进行排序,因为您是按排序顺序按等级访问元素的吗

您可以使用任何平衡二叉树的任何实现,每个节点上都有额外的信息,这些信息告诉您该节点的后代数(通常称为

通过这种结构,给定元素的排名(甚至最小/最大),您可以在O(logn)时间内访问/删除它

这使得所有操作(按排名访问/插入/删除、前/后弹出、按值插入/删除/搜索)都是O(logn)时间,同时允许自定义排序方法

此外,python显然有一个AVL树(最早的平衡树结构之一)实现,它支持顺序统计:


因此,您不需要自定义实现。

除了散列,您需要的是一个双端优先级队列,也称为优先级队列

如果您对排序的需求没有超出管理数据的最小值和最大值的范围,那么您可以查看的另一个结构可能是间隔堆,如果您需要查看值(尽管deleteMin和deleteMax仍然是O(log(N)),它的优点是O(1)查找最小值和最大值。不幸的是,我不知道Python中有任何实现,所以我认为您必须自己实现

下面是算法教科书的附录,如果您感兴趣,可以描述间隔堆:

如果您真的可以允许O(logn)用于pop、dequeue和insert,那么像红黑树这样的简单平衡搜索树就足够了

当然,您可以通过维护指向树中最小和最大元素的直接指针来优化它,然后在(1)向树中插入元素或(2)弹出或退出队列时更新它,这当然会使resp无效。指针。但是因为树是平衡的,所以仍然会出现一些混乱,您可以同时更新corr.指针

还有一种称为min-max heap(参见维基百科的二进制堆条目)的东西,它完全实现了一个“双端优先级队列”,即一个可以从前端和后端弹出的队列。然而,您不能按顺序访问整个对象列表,而搜索树可以在O(n)时间内高效地迭代


最小-最大堆的好处是当前的最小和最大对象可以在O(1)时间内读取,搜索树只需要O(log(n))来读取最小或最大对象,除非您有上面提到的缓存指针。

我假设“快速弹出”最多意味着O(log n)。但是插入新值需要多快?O(n)?O(logn)?O(1)?感谢KennyTM,澄清了这个问题。blist包看起来非常有前途,对
blist.blist()
执行O(logn)pop()操作。插入的渐进性能是什么?似乎是blist。sortedlist()不可能,因为它不允许从列表的末尾弹出,而只允许从列表的开头弹出。@fmark,使用
对分。在rt
中,插入到已排序的blist中应该是O(log**2 n)。这听起来像是一个最小-最大堆,加上一个哈希表,这就是我想要的。最小-最大堆很酷!在我之前在stackoverflow上发现它们之前,我实际上并不知道它们的存在:)