要搜索一组要包含的ip范围,正确的java数据结构和搜索算法是什么
如果IP地址范围为,则给出以下列表要搜索一组要包含的ip范围,正确的java数据结构和搜索算法是什么,java,Java,如果IP地址范围为,则给出以下列表 LOW HIGH 192.168.10.34 192.168.11.200 200.50.1.1 200.50.2.2 假设迭代所有范围内的所有地址并将其存储在哈希集中会占用太多内存 所以我们需要保持范围,实际上只是移位的数字(低和高)。 如何将范围存储在树中,然后使用有效的搜索来查找特定地址是否在范围内 我已经看过了,但它似乎在笛卡尔平面上搜索点,似乎不适合我的用例。允许搜索最近的邻居,当k==2时,它基本上与范围树相同 我想要所
LOW HIGH
192.168.10.34 192.168.11.200
200.50.1.1 200.50.2.2
假设迭代所有范围内的所有地址并将其存储在哈希集中会占用太多内存
所以我们需要保持范围,实际上只是移位的数字(低和高)。
如何将范围存储在树中,然后使用有效的搜索来查找特定地址是否在范围内
我已经看过了,但它似乎在笛卡尔平面上搜索点,似乎不适合我的用例。允许搜索最近的邻居,当k==2时,它基本上与范围树相同
我想要所有的比赛,因为可能会有多支安打
这里有什么用?我确信这是一个已解决的问题。如果我理解正确,您有一个范围列表,您希望将它们放入一个结构中,以便快速找到给定值所在的范围 您可以创建一个二元搜索树,该树存储范围两端的每个值(可能还有0.0.0.0),并在维护当前值所在的一组范围并将其副本设置为到达每个节点时的数据后,通过该树进行循环转发,然后,要找到给定IP所在的范围,只需使用二进制搜索找到低于该范围的最高界限值,与该值关联的集合就是给定IP所在的范围集合 这将是O(n^2)内存使用率(并且可能是O(n^2)时间来构造结构,假设复制需要基于被复制的数据大小的线性时间,我不记得了),但是单个查询将是O(logn)时间 这是一张图片,因为我觉得这不是一个很好的解释: 如果没有重叠范围,标准就可以了 只需创建一个
TreeMap
,由范围的低端键入,并将整个范围作为值。使用查找范围,并验证该值是否在范围内
示例:使用简单的Integer
而不是IpAddress
对象,但任何可比较的
对象都可以用作范围边界
public final class RangeMap<T extends Comparable<T>> {
private TreeMap<T, Range<T>> map = new TreeMap<>();
public void add(Range<T> range) {
Entry<T, Range<T>> entry = this.map.floorEntry(range.getUpperInclusive());
if (entry != null && entry.getValue().overlaps(range))
throw new IllegalArgumentException("Overlap: " + range + " vs " + entry.getValue());
entry = this.map.ceilingEntry(range.getLowerInclusive());
if (entry != null && entry.getValue().overlaps(range))
throw new IllegalArgumentException("Overlap: " + range + " vs " + entry.getValue());
this.map.put(range.getLowerInclusive(), range);
}
public boolean contains(T value) {
Entry<T, Range<T>> entry = this.map.floorEntry(value);
return (entry != null && entry.getValue().contains(value));
}
public Range<T> get(T value) {
Entry<T, Range<T>> entry = this.map.floorEntry(value);
return (entry != null && entry.getValue().contains(value) ? entry.getValue() : null);
}
}
Ip地址只有4个字节,即可以显示为32位
int
。将您的ip地址转换为int
s,然后简单地检查low我想他要求的算法比检查每个范围都要快。是的,我相信有比暴力线性搜索每个范围更有效的机制。我也不想枚举范围并将每个地址放入哈希集中。搜索速度会非常快,但会占用太多内存。@Jim只是想澄清一下,你说的是多少范围?十个?千百万?范围重叠吗?听起来很完美,我读了好几遍,但我还是不太明白它看起来像什么。。。对不起,这幅画有用吗?我觉得这个解释不是很好。不是真的,它不是一棵树?是的,我在写了这篇文章后意识到,甚至不需要一棵二进制搜索树,一个简单的IP/集合对排序数组也可以。树结构一点都不重要,只是值的分类。好吧,这仍然是一个很好的建议-这是一个好的开始。知道什么可以处理重叠范围会很好,但这其实不是一个问题,因为你可以分割重叠并单独添加,所以我认为你的解决方案会成功的,谢谢@Jim由于没有与某个范围相关的值(意思),您可以使用add()
方法将新范围与现有范围合并,例如,如果map包含[5-9,12-14]
,并且您添加8-12
,结果将是[5-14]
。然后可以添加<代码> Read()/<代码>方法,因此删除<代码> 6-9< /代码>将导致<代码> [5-5,10-14] < /代码>。@吉姆可以考虑重命名<代码> RangeMap <代码> > <代码>范围或<代码> RangeSET。树映射纯粹是内部映射。从外部看,您可以通过实现Iterable
及其iterator()
方法来迭代范围,方法是返回这个.map.values().iterator()代码>,从而使对象看起来像一组有序的非重叠(和非连续?)范围。
public final class Range<T extends Comparable<T>> {
private final T lowerInclusive;
private final T upperInclusive;
public Range(T lowerInclusive, T upperInclusive) {
this.lowerInclusive = lowerInclusive;
this.upperInclusive = upperInclusive;
}
public T getLowerInclusive() {
return this.lowerInclusive;
}
public T getUpperInclusive() {
return this.upperInclusive;
}
public boolean contains(T value) {
return (value.compareTo(this.lowerInclusive) >= 0 &&
value.compareTo(this.upperInclusive) <= 0);
}
public boolean overlaps(Range<T> that) {
return (this.lowerInclusive.compareTo(that.upperInclusive) <= 0 &&
this.upperInclusive.compareTo(that.lowerInclusive) >= 0);
}
@Override
public String toString() {
return "(" + this.lowerInclusive + "-" + this.upperInclusive + ")";
}
}
RangeMap<Integer> map = new RangeMap<>();
map.add(new Range<>(50, 59));
map.add(new Range<>(70, 79));
for (int i = 40; i <= 90; i += 3)
System.out.println(i + ": " + map.contains(i));