一 基树概念
Radix tree(也称为基树trie或紧凑trie)是一种空间优化的trie数据结构,用于存储关联数组,其中键是字符序列(例如,字符串或字节数组)。在基数树中,树中的每个节点表示一个或多个键的公共前缀,节点之间的边缘表示该前缀的扩展。由于它们的前缀共享,基数树可能比常规尝试更节省空间,特别是对于具有许多键共享公共前缀的数据集。注意:有的地方区分了Radix tree和Trie Tree,但是我觉得两者差不多,只是Radix Tree可以将多个字符分支叠加到一起,从而节省空间,如下图,不过我觉得这不影响问题的本质,只能算是一种压缩方式吧
Radix tree的工作原理是在树上建立一个前缀树,并在每个节点上存储一个字符串前缀。当查询字符串时,它可以从根节点开始遍历,并与每个节点的前缀进行比较,直到找到符合的节点为止。
Radix tree的优势在于支持高效的存储和查询,并且比其他树形数据结构更加紧凑,因此它是内存敏感型应用的理想选择。
Radix tree在很多领域都有广泛应用,如网络安全,路由,网络管理,字典管理等。在这些领域中,Radix tree可以用于存储并查询IP地址,规则集等信息。 总的来说,Radix tree是一种高效的、紧凑的树形数据结构,在很多领域都有广泛的应用。它可以用于存储和查询各种信息,从而提高应用的性能和效率。
二 CIDR的基树实现
2.1 初始简单版本
我们在进行IDS或路由的时候,经常会进行IP的匹配,利用基树实现是一种比较好的方式,利用java代码实现如下:
import java.util.*;
class RadixNode {
int value;
Map<Integer, RadixNode> children;
public RadixNode() {
children = new HashMap<>();
}
}
class RadixTree {
private RadixNode root;
public RadixTree() {
root = new RadixNode();
}
public void insert(String cidr) {
// 将CIDR格式切分成ip部分和网络地址的位数
String[] parts = cidr.split("/");
String[] ipParts = parts[0].split("\\.");
// 网络地址的位数
int prefixLength = Integer.parseInt(parts[1]);
// 获取mask
int mask = 0xffffffff << (32 - prefixLength);
RadixNode node = root;
for (int i = 0; i < ipParts.length; i++) {
// 对IP进行切分,每个元素都表示ip的一部分值
int b = Integer.parseInt(ipParts[i]);
int shift = 24 - 8 * i;
// 将每一部分进行移位 b & 0xff 更好的办法是和mask进行对应匹配
int key = (b & 0xff) << shift;
RadixNode child = node.children.get(key);
if (child == null) {
child = new RadixNode();
node.children.put(key, child);
}
node = child;
}
node.value = mask;
}
public int match(String ip) {
String[] ipParts = ip.split("\\.");
RadixNode node = root;
for (int i = 0; i < ipParts.length; i++) {
int b = Integer.parseInt(ipParts[i]);
int shift = 24 - 8 * i;
int key = (b & 0xff) << shift;
RadixNode child = node.children.get(key);
if (child == null) {
return 0;
}
node = child;
}
return node.value;
}
}
这个是对cidr进行简单的处理,将ipv4的代码按照点号切分后,每个部分,当作key存入到树中,叶子节点的值为mask的值。 代码还存在一些问题:
比如cidr必须严格按照子网掩码对ip取余后的再进行匹配。
上面直接定义HashMap来存储节点比较浪费内存。
测试代码:
RadixTree tree = new RadixTree();
tree.insert("192.168.2.0/24");
tree.insert("192.168.0.0/16");
int mask = tree.match("192.168.2.3");
System.out.println(Integer.toBinaryString(mask));
大概形成的树是:
黄色部分为叶子节点,括号里面是存的值。
2.2 优化内存占用版本
上面版本利用hashm
Radixtree在CIDR处理与内存优化中的应用

文章介绍了Radixtree(基树)作为一种空间优化的Trie数据结构,用于存储关联数组,特别是处理字符串或字节数组的键。通过示例展示了如何用Java实现基于CIDR的基树,包括从简单的HashMap到更节省内存的数组结构的优化。此外,文章提到了Radixtree在Suricata入侵检测系统中的应用,用于高效地进行IP地址匹配。
最低0.47元/天 解锁文章
1070

被折叠的 条评论
为什么被折叠?



