我得到了名为令牌的元素。他们中的每一个都是某种类型的关联容器(不一定是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])
答案 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中找到[在演讲的第一页复制权]