如何执行高效的交集操作?

时间:2012-02-17 08:23:30

标签: c++ algorithm

我得到了名为令牌的元素。他们中的每一个都是某种类型的关联容器(不一定是std容器之一)。我有一些类型的容器存储存储令牌(不一定是std容器之一)。存储令牌的集合。
我需要能够通过指定比较器的指定键对令牌值上的令牌集(存储)执行交集操作。 作为该操作的结果,我想获得另一组令牌(另一个存储)。

伪代码中的用例:

  if ( (storage0[key1]==storage1[key1])[key2]<storage1[key2] )
    ...

我正在寻找一种有效的算法 注意:我有几十个令牌 问题:
1)如何组织存储
2)如何实现交叉运行?

更新更多解释:
token是一组(键,值)对。 存储是一组(键,值)对

我需要交叉(P1,K1,P2,K2,cmp)
P1 - 第一次存储
P2 - 第二次存储
K1 - 第一次存储的钥匙
K2 - 第二次存储的钥匙
cmp - 比较函数,如cmp(value,value),返回true或false

Intersect应该遍历P1的每个元素e1,并且遍历P2的每个元素e2 并提取满足cmp的元素((键,值)对)(e1 [K1],e2 [K2])

1 个答案:

答案 0 :(得分:1)

Inverted index可以有效地处理交叉点,因此您可以执行类似的操作。

这个想法是:每个集合实际上都是一个列表,具有高效的getFirstAfter(key)函数 - 它返回key之后的第一个标记。对于每个集合 - 您需要检查相关元素是否在其中 - 如果不存在 - 则前进到集合中的下一个元素。

(*)请注意,此算法中列举了令牌

(*)假设T持有你想要交叉的所有列表[算法有效地交叉多于两个列表]

Psudo代码:

lastTok <- 0 //the first token in the collection
currSet <- 0 //the first set 
while (lastTok != infinity):
  if (currSet > T.last): //if we have passed the last set
     insert lastTok into result
     currSet <- 0
     lastTok <- lastTok + 1
     continue
  currentToken<- T[currSet].getFirstAfter(lastTok-1)
  if (currentToken!= lastTok):
     lastTok<- currentToken
     currSet <- 0
  else: 
     currSet <- currSet + 1

此算法假设有效getFirstAfter(),它可以为您提供符合该术语的第一个文档,并且他的docId大于指定的参数。如果没有,它应该返回无穷大。

如果对术语进行排序,使得最稀有的术语是第一个,则该算法将是最有效的。

该算法最多可确保#docs_matching_first_term * #terms次迭代,但实际上 - 迭代次数通常会少得多。

更多信息可以在this lecture notes幻灯片11-13中找到[在演讲的第一页复制权]