哪种数据结构适用于此?

时间:2015-05-27 18:38:21

标签: python algorithm list data-structures

我的代码中有一行当前在每个步骤x执行此操作:

myList = [(lo,hi) for lo,hi in myList if lo <= x <= hi]

这很慢。是否有更有效的方法从列表中删除不包含给定x的内容?

3 个答案:

答案 0 :(得分:3)

也许您正在寻找interval tree。来自维基百科:

  

在计算机科学中,区间树是用于保持区间的有序树数据结构。具体来说,它允许人们有效地找到与任何给定间隔或点重叠的所有间隔。

因此,不是将(lo, hi)对按顺序存储在列表中,而是让它们在区间树中定义间隔。然后,您可以使用x对树执行查询,并仅保留重叠x的区间。

答案 1 :(得分:0)

虽然你没有提供太多的上下文,但我会假设循环的其余部分如下:

for x in xlist: myList = [(lo,hi) for lo,hi in myList if lo <= x <= hi]

在这种情况下,首先构建区间树(http://en.wikipedia.org/wiki/Interval_tree)可能更有效。然后,对于每个x,您走树,找到与x相交的所有区间;在找到它们时将这些间隔添加到一个集合中。

答案 2 :(得分:0)

在这里,我将建议看起来似乎是一个非常愚蠢的解决方案,有利于微算优化算法。这取决于您的具体需求。

最终的问题是:对你的数组进行线性传递(Python中的列表),平均而言,价格昂贵?换句话说,搜索包含x的lo / high对通常会产生非常小的结果(例如:列表整体大小的1%),或相对较大(例如:25%)或更多的原始清单)?

如果答案是后者,您实际上可能会获得一个更有效的解决方案,保持您按顺序访问的基本,连续,缓存友好的表示形式。硬件缓存擅长于通过连续数据进行耕作,其中多个相邻元素按顺序放入缓存行。

在这种情况下,您要避免的是从阵列中间移除昂贵的线性时间以及可能构建新阵列。如果你为从阵列中删除的每个单个元素触发线性时间操作,那么自然会很快变得非常昂贵。

要以更快的常量时间交换线性时间操作,当我们想要删除数组中某个索引处的元素时,我们所要做的就是用该元素覆盖该索引处的元素数组的后面(最后一个元素)。现在只需从数组后面删除冗余副本(从数组后面删除是一个常数时间操作,通常只涉及基本的算术指令)。

如果您的需求符合标准,那么这实际上可以提供比智能算法更好的结果。由于硬件缓存在DRAM上的性能偏差,这种做法可以胜过理论,这是一种特殊情况,但如果你反复执行这些类型的hi / lo查询并希望得到非常窄的结果,那么更聪明的东西像间隔树或至少对数据进行排序以允许二进制搜索可以相当好。