Answers:
如果每个集合都维护着其他集合的记录,并且您总共有集合,则可以轻松地将集合的任何数据结构(例如,二进制搜索树等)转换为可以检索的集合时间两组交集的一个元素。
每个集合应具有某些完全有序集合的唯一标识符。如果您明确命名集那么标识可能只是索引。
您应该对集合进行“注册”;维护您定义的所有集合的集合的数据结构。注册表应实现为搜索树数据结构,以允许轻松检索(例如, 如果您要删除集合)和线性遍历集合。
每个集合还维护其他每个集合的“索引” ,而不是它们的副本,而是维护由其他集合的标签索引的数据结构。该指数将被用于保持,对于每组小号ķ,所有的元件的二叉查找树小号Ĵ ∩ 小号Ĵ。(两组和 S k共享该搜索树的一个副本。)
初始化
一组初始化由Ô (1 )操作,以初始化它的元素的树,Ô (小号)作为初始化操作(从注册表复制)对于该组的索引Ť,和ø (小号日志小号)遍历注册表时将T添加到其他每个S集的索引中的操作。在指数牛逼,我们创建表示搜索树牛逼∩ 小号Ĵ = ∅对于其他集 ; 我们为S j的索引复制相同的指针。
将元素添加到集合
加入一些所设定的Ť需要时间ø (登录Ñ Ť)照常,其中Ñ Ť = | T | 。我们还测试了x在其他每个集合S 1,S 2,...中的隶属关系,这需要花费时间O (log n S 1 + log n S),其中n = |。V |
如果你不允许在台重复的,我们可以节省时间的情况下已经放弃了其他组成员检测和插入牛逼。x的情况下为“插入”已经存在仅花费时间。
交叉口测试
精确地维护每个集合的索引,以便快速评估两个集合和S k是否相交。对于集合S j,只需检查其索引以获取集合S k,我们不仅可以在时间O (log s )中确定S j是否与S k相交。,而且还可以检索包含整个集合的二叉树。。
元素去除
要删除一个元素从一组牛逼,我们不仅从搜索树中删除它牛逼本身,而是来自各个路口的小号Ĵ ∩ 牛逼的套小号Ĵ在其索引。这需要时间O (s log n T),其中n T = | |。T | 。
集合删除
由于搜索注册表的开销,如果您有很多集合,则可能需要在不再需要它们时删除它们。通过遍历整个注册表,我们可以删除从所有其他组的索引小号Ĵ及时Ø (S ^ ñ 牛逼)中,删去表示搜索树的成本主导小号Ĵ ∩ 牛逼其他每个组的小号Ĵ,其中n T = | T | 。
备注
如果您希望仅实现恒定数量的集合,那么上述运行时间将减少为:
初始化:
元素插入:
相交测试(和相交的检索):
元素去除:
集删除:
其中是注册表中最大集合的大小,n T = | T | 对于您正在操作的集合T。
如果您希望将临时设置为每个新集合到与T相交的其他集合T的索引中集,其中是您的Universe,则希望这些运算在亚线性时间内运行,则可能需要其他数据结构。但是,如果您有几对您知道永远不会进行测试的交集,则可以减少这些集的索引大小(不包括要测试其交集的任何集合),或者使用多个注册表(每个可能要测试其交集的集合的集合之一。实际上,只有在您希望集中控制以确保每对集合在索引中具有彼此的记录时,注册表才有用:在某些情况下,初始化集合S时,仅记录即可在某些情况下可行你感兴趣的内容。
即使在最坏的情况下,也有一些数据结构可让您在不到线性时间内完成此操作。请参阅http://research.microsoft.com/pubs/173795/vldb11intersection.pdf(以及其中的论文参考)。
如果您的两个集合S和T的交集较大,并且有一个S字典,那么按随机顺序查找T的元素应该很快就会为您提供一个公共元素。最困难的情况是交点大小为0或1。
通常,您选择的编程语言将支持具有唯一元素的数据结构。通常,有三种流行的方法:树,哈希和位掩码。树元素必须具有可比性,哈希元素必须是可哈希的,而位掩码元素必须具有某种转换为整数的方式。
树集将支持在O(log n)中插入和在最坏情况O(n log n)中进行交集测试。
哈希集将支持在摊销O(1 * h)中插入,其中“ h”是哈希算法的运行时间,并支持最坏情况O(n)中的交集测试。
位掩码集通常不像树集和哈希集那样使用。
如果您的情况允许错误的肯定答案,那么我将使用具有单个哈希函数的Bloom Filter。
您可以如下实现:
初始化一个空集
将元素添加到集合中。
给定两个集合(B1,B2),报告它们是否相交。
复杂