我正在寻找一种有效的方式来存储有序列表/项目集:
理想情况下,性能会偏向于检索任何子集(或合并子集)的前N个项目,并且存储将在内存中(并且最终可能在磁盘上持久存储)
答案 0 :(得分:2)
我是这个论坛的新成员,我希望你没有忘记这个老问题:)
将主集存储在索引数据结构中 - 例如数组(或arraylist,如果您的库支持它)。假设您可以将id与每个集合关联(如果没有,那么您如何知道要检索哪个集合?)。因此,我们现在需要一种方法来找出阵列中哪些元素参与该集合以及哪些元素不参与。
使用矩阵(n x m)
,n
是数组中元素的数量,m
是初始数量。 i引用行索引,j引用列索引。
A[i][j] = 0 if ith element is not in jth set
A[i][j] = 1 if ith element is in jth set
不要使用简单的二维数组,请选择ArrayList<ArrayList>
。 Java / C#/ C ++支持这样的通用构造,但在其他语言(如Perl)中这样做并不是非常困难。在C#中,您甚至可以使用DataTable
。
您可以在O(n)
时间内添加新内容。只需为该集添加新列,并为该列设置适当的行为1。只要原始数组已排序,就不需要对此集进行排序。
在简单的排序数组中,插入时间为O(log n)
。在我们的例子中,我们首先将元素添加到数组中(在我们添加元素的任何索引处,矩阵也将在该索引处获得所有0
行)。然后,如果元素属于集合,我们将该列中的条目设置为1。这样,最坏的情况运行时变为O(log n) + O(m)
。
在O(1)
时间内选取与该集相对应的列,然后选择N
的第一个1
条目。这将是线性的。
假设我们将j1和j2的集合合并到j3的第三集。
for (int i = 0; i < n - 1; i++) {
A[i][j3] = A[i][j1] | A[i][j2];
}
这又是线性的。
首先在主数组中找到元素 - 这需要O(log n)
次。然后从该数组中删除它,并从矩阵中删除该索引处的行。
不要简单地删除,只是将它们标记为已解散。在阈值数量的已解散的列/行后,您可以合并。同样,最初从阵列的高容量开始。现代实现应该自动执行此操作。