集合相交的数据结构?


21

是否有任何数据结构可以维护(有限基础集的)集合的集合,从而支持以下操作?任何亚线性运行时间将不胜感激?

  1. 初始化一个空集。
  2. 将元素添加到集合中。
  3. 给定两个集合,报告它们是否相交。

1
这是一个非常笼统的问题,因为任何数据结构都可以在有限域中支持这些操作。您能具体一点吗?例如。您需要什么复杂性,为进行固定操作等您愿意牺牲什么?
Bartosz Przybylski 2013年

Answers:


13

如果每个集合都维护着其他集合的记录,并且您总共有s>0集合,则可以轻松地将集合的任何数据结构(例如,二进制搜索树)转换为可以检索的集合时间两组交集的一个元素O(logs)

  • 每个集合应具有某些完全有序集合的唯一标识符。如果您明确命名集S1,S2,那么标识可能只是索引。

  • 您应该对集合进行“注册”;维护您定义的所有集合的集合的数据结构。注册表应实现为搜索树数据结构,以允许轻松检索(例如,  如果您要删除集合)和线性遍历集合。

  • 每个集合还维护其他每个集合的“索引” ,而不是它们的副本,而是维护由其他集合的标签索引的数据结构。该指数将被用于保持,对于每组小号ķ,所有的元件的二叉查找树小号Ĵ小号ĴSjSk。(两组和 S k共享该搜索树的一个副本。)SjSkSjSk

初始化

一组初始化Ô 1 操作,以初始化它的元素的树,Ô 小号作为初始化操作(从注册表复制)对于该组的索引Ť,和ø 小号日志小号遍历注册表时将T添加到其他每个S集的索引中的操作T=O(1)O(s)TO(slogs)T。在指数牛逼,我们创建表示搜索树牛逼小号Ĵ = SjTTSj=对于其他集 ; 我们为S j的索引复制相同的指针。SjSj

将元素添加到集合T

加入一些所设定的Ť需要时间ø 登录Ñ Ť照常,其中Ñ Ť = | T | 。我们还测试了x在其他每个集合S 1S 2...中的隶属关系,这需要花费时间O log n S 1 + log n S其中n = |。V |xVTO(lognT)nT=|T|xS1,S2,

O(lognS1+lognS2+)O(slogn),
n=|V|是宇宙的大小(或最大集合),而s是注册表中集合的数目。对于每一组小号Ĵ使得X 小号Ĵ,还插入X成用于该集合中的索引小号ĴŤ。对于每个这样的集合S j,这需要O log s + log n T时间来查找 S jSjsSjxSjxSjTSjO(logs+lognT)Sj中的索引并插入X小号ĴŤ ;在所有套小号1s ^ 2TxSjT这需要时间 O s log s + s log n T。如果我们假设集合数 S j小于宇宙 V的大小(也就是说,如果我们假设 sS1,S2,O(slogs+slognT)SjV),用于插入元件的总时间然后 ø 小号日志Ñ snO(slogn)

如果你不允许在台重复的,我们可以节省时间的情况下已经放弃了其他组成员检测和插入牛逼x的情况下为“插入”xSTx已经存在仅花费时间O(lognT)

交叉口测试

精确地维护每个集合的索引,以便快速评估两个集合S k是否相交。对于集合S j,只需检查其索引以获取集合S k,我们不仅可以在时间O log s )中确定S j是否与S k相交。SjSkSjSkO(logs)SjSk,而且还可以检索包含整个集合的二叉树。SjSk

元素去除

要删除一个元素从一组牛逼,我们不仅从搜索树中删除它牛逼本身,而是来自各个路口的小号Ĵ牛逼的套小号Ĵ在其索引。这需要时间O s log n T,其中n T = | |。T | xTTSjTSjO(slognT)nT=|T|

集合删除

由于搜索注册表的开销,如果您有很多集合,则可能需要在不再需要它们时删除它们。通过遍历整个注册表,我们可以删除从所有其他组的索引小号Ĵ及时Ø S ^ ñ 牛逼中,删去表示搜索树的成本主导小号Ĵ牛逼其他每个组的小号Ĵ,其中n T = | T | SSjO(snT)SjTSjnT=|T|

备注

如果您希望仅实现恒定数量的集合,那么上述运行时间将减少为:

  • 初始化:O(1)

  • 元素插入:O(logn)

  • 相交测试(和相交的检索):O(1)

  • 元素去除:O(lognT)

  • 集删除:O(nS)

其中是注册表中最大集合的大小,n T = | T | 对于您正在操作的集合T。nnT=|T|T

如果您希望将临时设置为每个新集合到与T相交的其他集合T的索引中O(|V|)集,其中是您的Universe,则希望这些运算在亚线性时间内运行,则可能需要其他数据结构。但是,如果您有几对您知道永远不会进行测试的交集,则可以减少这些集的索引大小(不包括要测试其交集的任何集合),或者使用多个注册表(每个可能要测试其交集的集合的集合之一。实际上,只有在您希望集中控制以确保每对集合在索引中具有彼此的记录时,注册表才有用:在某些情况下,初始化集合S时,仅记录即可在某些情况下可行VST你感兴趣的内容。S



3

通常,您选择的编程语言将支持具有唯一元素的数据结构。通常,有三种流行的方法:树,哈希和位掩码。树元素必须具有可比性,哈希元素必须是可哈希的,而位掩码元素必须具有某种转换为整数的方式。

树集将支持在O(log n)中插入和在最坏情况O(n log n)中进行交集测试。

哈希集将支持在摊销O(1 * h)中插入,其中“ h”是哈希算法的运行时间,并支持最坏情况O(n)中的交集测试。

位掩码集通常不像树集和哈希集那样使用。


2
这将是一个不错的Stack Overflow答案,但是在这里我们想了解如何工作以及为什么起作用的一些细节。
拉斐尔

3

如果您的情况允许错误的肯定答案,那么我将使用具有单个哈希函数的Bloom Filter

您可以如下实现:

初始化一个空集

  • = n位的位阵列,所有位都设置为0。(应根据可能的元素数选择 nBnn

将元素添加到集合中。

  • B[hash(element)]=1

给定两个集合(B1,B2),报告它们是否相交。

  • 检查A N D B 2 = 0B1 AND B2 = 0

复杂

  • 如果不太大,则所有操作均为O 1 nO(1)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.