我想实现一个可变的顺序集合FilteredList
,它包装另一个集合List
并根据谓词对其进行过滤。
包装的List
和公开的FilteredList
都是可变的和可观察的,并且应该是同步的(例如,如果有人向List
添加了一个元素应该出现在FilteredList
中的正确位置,反之亦然。)
不满足谓词的元素仍然可以添加到FilteredList
,但它们将不可见(它们仍会出现在内部列表中)。
馆藏应该支持:
Insert(index,value)
在位置value
插入元素index
,向前推送元素。Remove(index)
删除位置index
的元素,移回所有前进元素。Update(index, value)
,将位置index
的元素更新为value
。 我在找到一个好的同步机制时遇到了麻烦。
我没有任何严格的复杂范围,但现实世界的效率很重要。
答案 0 :(得分:1)
避免同步困难的最佳方法是创建一个不需要它们的数据结构:使用单个数据结构来显示已过滤和未过滤的数据。
您应该可以使用修改后的skip list(实际上是indexable skip list)执行此操作,这将通过索引为您提供O(log n)访问权限。
您所做的是为每个节点维护两组不同的前向指针,而不仅仅是一组。一组用于未过滤列表,如普通跳过列表,另一组用于过滤列表。
对于已过滤和未过滤的列表,添加到列表或从列表中删除是相同的。也就是说,通过遵循适当的过滤或未过滤链接,在索引处找到节点,然后添加或删除节点,更新两组链接指针。
这应该比标准顺序列表更有效,因为插入和移除不会产生向上或向下移动项目以造成漏洞或填补空白的成本;这一切都完成了参考。
但每个节点需要更多的空间。平均而言,跳过列表每个节点需要两个额外的引用。由于您正在构建两个跳过列表中的两个跳过列表,因此平均每个节点需要四个额外的引用。
如果,如你所说,你不控制List
,那么你仍然保持我描述的这个双重跳过列表。但是存储在跳过列表中的数据只是List
的索引。您说List
是可观察的,因此您可以获得所有插入和删除操作的通知,因此您应该能够通过对所有通知作出反应来维护索引。
当某人想要对FilteredList
进行操作时,您可以使用过滤后的索引链接查找用户想要影响的List
记录的FilteredList
索引。然后使用翻译的索引将请求传递到List
。然后您对来自List
的可观察通知做出反应。
基本上,您只是将二级索引维护到List
,以便将FilteredList
索引转换为List
索引。