有人知道这个Python数据结构吗?

时间:2010-11-04 15:19:55

标签: python performance sorting insert deque

Python类有六个要求,如下所示。只有粗体字才能被视为要求。


  1. 对于以下四项操作中的任意一项,接近 O(1)表现
  2. 在将对象插入容器时维护排序顺序。
  3. 能够查看对象中包含的最后一个值(最大值)。
  4. 允许双方弹出(获取最小或最大值)。
  5. 获取总大小的能力或存储的对象数。
  6. 是一个现成的解决方案,就像Python标准库中的代码一样。

  7. 由于历史原因,这里留下了什么(帮助好奇并证明进行了研究)。


    在查看Python的标准库(特别是关于数据类型的部分)之后,我仍然没有找到满足碎片表要求要求的类。 collections.deque接近所需,但它不支持保持其中包含的数据排序。它提供:

    1. O(1)表现
    2. 的双端队列两侧有效追加和弹出。
    3. 双方弹出以查找对象中包含的数据。
    4. 获取总大小或其中包含的对象数。
    5. 使用列表实现低效的解决方案将是微不足道的,但找到一个表现良好的类将更加可取。在不增加上限的增长内存模拟中,这样的类可以保留空(已删除)单元格的索引并保持碎片级别下降。 bisect模块可以提供帮助:

      1. 帮助在排序顺序中保留数组,同时在数组中插入新对象。
      2. 现成的解决方案用于保持按对象排序的列表。
      3. 允许执行array[-1] 查看数组中的最后一个值
      4. 最终候选人未能完全满足要求且看起来最不乐观的是heapq模块。虽然支持看似有效的插入并确保array[0]是最小值,但数组并不总是处于完全排序状态。没有其他任何东西被发现有帮助。


        有没有人知道Python中的类或数据结构接近这六项要求?

3 个答案:

答案 0 :(得分:11)

您的要求似乎是:

  1. O(1)从两端弹出
  2. 高效len
  3. 排序顺序
  4. 查看最后一个值
  5. 您可以使用deque使用自定义insert方法旋转双端队列,将其附加到一端,然后取消旋转。

    >>> from collections import deque
    >>> import bisect
    >>> class FunkyDeque(deque):
    ...     def _insert(self, index, value):
    ...             self.rotate(-index)
    ...             self.appendleft(value)
    ...             self.rotate(index)
    ...
    ...     def insert(self, value):
    ...             self._insert(bisect.bisect_left(self, value), value)
    ...
    ...     def __init__(self, iterable):
    ...             super(FunkyDeque, self).__init__(sorted(iterable))
    ...
    >>> foo = FunkyDeque([3,2,1])
    >>> foo
    deque([1, 2, 3])
    >>> foo.insert(2.5)
    >>> foo
    deque([1, 2, 2.5, 3])
    

    请注意,要求1,2和4都直接遵循以下事实:基础数据结构是双端队列,并且由于插入数据的方式,要求3成立。 (当然请注意,您可以通过调用例如_insert来绕过排序要求,但这不是重点。)

答案 1 :(得分:8)

非常感谢katrielalex提供了导致以下Python类的灵感:

import collections
import bisect

class FastTable:

    def __init__(self):
        self.__deque = collections.deque()

    def __len__(self):
        return len(self.__deque)

    def head(self):
        return self.__deque.popleft()

    def tail(self):
        return self.__deque.pop()

    def peek(self):
        return self.__deque[-1]

    def insert(self, obj):
        index = bisect.bisect_left(self.__deque, obj)
        self.__deque.rotate(-index)
        self.__deque.appendleft(obj)
        self.__deque.rotate(index)

答案 2 :(得分:2)

blist.sortedlist

  1. 在以下四项操作中接近O(1)表现。
  2. 在将对象插入容器时维护已排序的顺序。
  3. 能够查看对象中包含的最后一个值(最大值)。
  4. 允许双方弹出(获取最小或最大值)。
  5. 获得存储的对象总数> 的能力。
  6. 是一个现成的解决方案,就像Python标准库中的代码一样。
  7. 这是B +树。