排序列表与堆:在列表中间删除元素Python

时间:2018-08-26 18:44:31

标签: python-3.x list performance heap

我的列表结构不断更新。在每次迭代中,都执行以下步骤:

  • 删除列表中的最小值
  • 删除列表中某处的n个值
  • 将n个值添加到列表中

据我了解,这里的堆不是一个好的解决方案(即使使用延迟删除),因为我需要删除列表中某个我不知道其索引(位置)的值。因此,需要搜索这些值。

我是否仅使用排序列表来解决此问题?我需要这里可以达到的最佳性能,因为在循环的某个时刻列表最多包含100.000个元素。

2 个答案:

答案 0 :(得分:1)

如果可以将值用作dict键,那么使用堆和collections.Counter来跟踪概念上仍在集合中的每个值将非常容易。计数为0表示该值在概念上已被完全删除,尽管它可能仍存在于堆中。

这是一个草图(未经测试!),其中ccollections.Counter的实例,而h是用作heapq模块操作的堆的列表:< / p>

要添加元素(堆大小的预期情况下时间为对数):

heapq.heappush(h, elt)
c[elt] += 1

要删除元素(预期情况下的恒定时间):

if not c[elt]:
    raise ValueError("element doesn't exist")
c[elt] -= 1
if not c[elt]:
    del c[elt]

要删除最小元素(从堆中弹出的每个概念上已经删除的项目的预期对数时间(以堆的缩小大小为单位)):

while True:
    if not h:
        raise ValueError("cannot find minimum in empty collection")
    elt = heapq.heappop(h)
    if c[elt]:
        c[elt] -= 1
        if not c[elt]:
            del c[elt]
        break
    # else the Counter believes it was deleted earlier

答案 1 :(得分:0)

通过在堆旁边维护一个字典,可以避免不知道要删除的项目的索引的问题。字典中的值与堆项目相同(也许是具有优先级值的列表和对实际项目的引用)。字典键与真实项相同,因此易于查找。

要删除非最小项目时,可以在字典中查找该项目并将其标记为已删除(也许通过将对项目的引用设置为None)。无需修改表示堆的列表,它具有对相同项目的引用,因此,只要出现要删除的项目,它就会被视为已删除。

也就是说,如果您经常执行“从数据中的任何地方删除项目”操作,那么仅使用常规词典或集合可能会更好。您可以在线性时间内使用min来获得最小值,并且除去(包括最小项在内的任何项目)都需要固定时间(平均摊销)。对于某些使用模式,可能比处理堆要快。