需要一种算法将网络范围折叠成超集范围列表

时间:2008-09-29 16:48:20

标签: algorithm superset

我的数学失败让我失望!我需要一种有效的方法来减少超集的网络范围,例如:如果我输入IP范围列表:

  • 1.1.1.1至2.2.2.5
  • 1.1.1.2至2.2.2.4
  • 10.5.5.5至155.5.5.5
  • 10.5.5.6至10.5.5.7

我想返回以下范围:

  • 1.1.1.1至2.2.2.5
  • 10.5.5.5至155.5.5.5

注意:输入列表没有排序(尽管它们可能是?)。执行此操作的简单方法是检查列表中的每个范围,以查看输入范围x是否为子集,如果是,则不插入范围x。但是,无论何时插入新范围,它都可能是现有范围的超集,因此您必须检查现有范围以查看它们是否可以折叠(例如,从我的列表中删除)。

4 个答案:

答案 0 :(得分:16)

这是段计算的联合。最佳算法(在O(nlog(n))中包括执行以下操作:

  1. 对列表L中的所有端点(起点和终点)进行排序(每个端点应该知道它所属的段)。如果端点等于起点,则应将起点视为小于enpoint。
  2. 从左到右浏览排序列表L并保持数字 LE-RE ,其中 LE 是您已经传递的左端点数,以及 RE 是您已经传递的右端点数。
  3. 每当 LE-RE 达到零时,您就处于连接的段联合的末尾,并且您知道之前看到的段的并集(自上次返回零以来) )是一个超集。
  4. 如果你还保持最小值和最大值,每次返回零之间,你就有超集的界限。
  5. 最后,您将获得一个不连续的超集的排序列表。两个超集A和B可以相邻(A的端点恰好在B的起点之前)。如果你想要合并A和B,你可以通过一个简单的后处理步骤,或者通过稍微修改第3步来做到这一点:当 LE-RE 达到零时,你会认为它是一个结束仅当L中的下一个元素不是当前元素的直接后继时才超集。

答案 1 :(得分:4)

您知道可以轻松地将IPv4地址转换为int数字(int32数字),对吗?使用int数字要容易得多。所以基本上每个地址都是0到2 ^ 32范围内的数字。每个范围都有一个起始编号和一个结束编号。你的例子

1.1.1.1 to 2.2.2.5
1.1.1.2 to 2.2.2.4

可以写成

16,843,009 to 33,686,021
16,843,010 to 33,686,020

所以很容易看出一个范围是否在另一个范围内。如果给出以下条件,则范围完全在另一范围内

startIP2 >= startIP1 && startIP2 <= endIP1 &&
endIP1 >= startIP1 && endIP2 <= endIP1

在这种情况下,范围startIP2-endIP2完全在startIP1-endIP1内。如果只有第一行为真,则startIP2在startIP1-endIP1范围内,但结束超出范围。如果仅第二行为真,则endIP在该范围内,但是起始IP超出范围。在这种情况下,如果只有一行为真,则需要在开头或结尾扩展范围。如果两条线都是假的,则范围完全不相交,在这种情况下,它们是两个完全独立的范围。

答案 2 :(得分:0)

您需要做的只是检查重叠范围。如果两个范围重叠,则它们将合并为单个范围。如果一个范围的右侧大于另一个范围的左侧,则范围重叠。

答案 3 :(得分:0)

好吧,我的同事想出了这个答案,我认为这个答案非常好。如果您发现任何问题,请告诉我们:

  • 通过StartingIP
  • 订购IP范围
  • 对于要插入的每行“x”:
    • 如果列表中有前一行“y”,则获取:
      • 如果x和y是连续的,则将y扩展为x的EndingIP
      • 如果x.StartingIP&lt; = y.StartingIP和x.EndingIP&gt; y.EndingIP,将y扩展为x.EndingIP
      • 否则,如果x是y的子集,则不执行任何操作
      • 否则,请创建一个新范围
    • 否则,创建一个新范围并插入列表