我必须编写非常快的算法,以便将IP地址与组列表进行匹配,其中每个组使用192.168.0.0/252.255.0.255等符号进行定义。如您所见,位掩码即使在中间也可以包含零,因此传统的“最长前缀匹配”算法将无法工作。如果IP匹配两个组,则将其分配给网络掩码中包含大多数1的组。
我没有使用很多条目(假设< 1000)并且我不想使用需要大量内存占用的数据结构(假设> 1-2 MB),但它确实需要快(当然我买不起线性搜索)。
你有什么建议吗?谢谢你们。
更新:我在http://www.cse.usf.edu/~ligatti/papers/grouper-conf.pdf找到了一些非常有趣的东西,但是对于我的乌托邦用例来说,它仍然太缺乏记忆力
答案 0 :(得分:1)
如果你知道最初会处理多少个IP地址,我会说使用哈希地图结构。对于此映射的键,将IP转换为整数类型结构。哈希映射,假设一个好的哈希函数(没有冲突),将给你O(1)插入和O(1)查找。
如果您不知道自己拥有多少IP,请考虑使用Fibonacci Heap(我认为具有插入/所有树结构中最佳时间复杂度)删除/查找)。
您可以使用的另一种结构是Radix Sort。
您对算法必须采用的时间有任何具体要求吗? “真的,真的,非常快”有点模糊。
答案 1 :(得分:1)
您构建了一个二进制树,可以单独检查这些位。您以一种给您“最丰满的树”的形式订购比特支票。您有一个后期订单遍历,以便在退出前检查完整深度,从而返回最长的点击。
伪代码
nodeCheck(bitVector, index){// bitvector is ordering of IP address bits for bushy tree
if myVal=-2 (return -1); //mismatched bit encountered No point continuing.
lVal,Rval=-1;
if (Left !=NULL && bitvector[index]==0) lVal=Left.nodeCheck(bitvector, index+1);
if (Right !=NULL && bitvector[index]==1) rVal=Right.nodeCheck(bitvector, index+1);
if (lVal>rVal) return lVal; // higher numbers have >= number of 1's in netmask.
if (rVal >-1) return rVal;
return myVal; //the group that getting this far would place you in, -1 if none.
}
确定速度你想要跳过OO因子,但概念是相同的。
逻辑有点不稳定,但这个想法很合理。
但是考虑到你有radixTree,我不想太深入了。 邮政订单遍历只是让你抓住最长的匹配而不会太奇怪。
答案 2 :(得分:1)
简单的答案是命令你的位适合你的树。让你的树尽可能浓密(实际上很短)。
更彻底的回答:
由于这些长度相同,因此它们的顺序无关紧要
让我们来电话
0.0.0.0/255.255.0.255 A.
0.0.0.0/255.255.255.0 B.
传入0.0.111.0
octet 1 2 3 4我们有正确的订购
我打算用八位字母做这些,因为我很懒。 要制作最丰满的树,你需要检查八位位组3或4作为你的第一个测试3是较低的将采取任意优先。
因此,这会查看值,并检查右侧分支。右手分支是另一个节点,它检查八位字节,然后向下移动左手分支,到下一个检查八位位组2的节点,这检查左(八位位组4)并得到-1(通过NULL),右边和得到-1(通过NULL),所以它返回A(我们称之为枚举类型)。
因此,八位位组排序变为3 1 2 4。
通常,您需要对位检查进行排序,以便早期级别进行某种检查。在这种情况下,我们将4推到最后,因为如果三个命中(为零),对八位位组4的检查是浪费而不需要完成。但无论第一次检查的结果如何,都需要完成1和2。
在一个更大的问题上会有一些没有检查的节点,无论所包含的位的值如何,都将它们发送到相同的左右分支。
构建不良的有效树可能需要3 4 1 2的顺序,所以如果第一次检查通过(0而不是111),则第二次检查是浪费,因为我们已经属于B组,无论八位组的值如何4.
祝你好运。