存储多个数字范围以便将来搜索的有效方法

时间:2016-04-20 15:52:51

标签: java algorithm performance

我有一个充满IP地址范围的文本文件。我使用ip2long将地址转换为long,以便我可以轻松检查给定地址是否在范围内。但是,我正在寻找一种有效的方法来存储这些范围,然后搜索以查看任何范围内是否存在IP地址。

我想到的当前方法是创建一个具有范围的低端和高端的对象,其功能是检查该值是否在范围内。我会将这些对象存储在列表中并检查每个对象。但是,我觉得这可能有点低效,随着列表的增加可能会变慢。

有没有比我想的更好的方式?

2 个答案:

答案 0 :(得分:3)

以下数据结构之一可能对您有所帮助:

细分树

来自WikipediaImplementation):

  

是用于存储间隔或段的树数据结构。它允许查询哪个存储的段包含给定的点。

间隔树

来自WikipediaImplementation):

  

是用于保持间隔的树数据结构。具体来说,它允许人们有效地找到与任何给定间隔或点重叠的所有间隔。

范围树

来自WikipediaImplementation):

  

是一个有序的树数据结构,用于保存点列表。它允许有效报告给定范围内的所有点。

答案 1 :(得分:2)

假设范围不重叠,否则您可以将它们组合成一个范围。

然后创建一个越来越有序的begin1, end1, begin2, end2, ...数组。 begini包含在范围内的位置,endi就在范围之后。

现在进行二分查找:

int pos = ... .binarySearch ...
boolean found = pos >= 0;
if (!found) {
    pos = ~pos;
}
boolean atBegin = pos % 2 == 0;
boolean insideRange = (found && atBegin) || (!found && !atBegin);
//Equivalent: boolean insideRange = found == atBegin;

查找测试是O(log N)。初始数组的创建要复杂得多。

Java binarySearch在找到时提供索引,并在找不到时索引(补码,< 0)。

附录:我认为以上内容可以巧妙地"由

组成
boolean insideRange = (Arrays.binarySearch(...) & 1) == 0;

虽然肯定需要解释性评论。我把它留给读者。