我有一个大型系统使用AVL树来快速搜索IP地址:
struct avl_node
{
struct avl_node *left;
struct avl_node *right;
...
void *info; /* point to nhlfe_entry describing nexthop */
}
struct nhlfe_entry
{
u_int32_t nhlfe_ix;
u_char opcode;
...
struct nhlfe_key key;
}
/* defines a search key. */
struct nhlfe_key
{
struct in_addr nh_addr;
u_int32_t oif_ix;
u_int32_t out_label;
}
所以搜索基于'struct nhlfe_key',即比较器函数 AVL树看起来像这样:
static int
mpls_cmp_nhlfe_ipv4_key (void *data1, void* data2)
{
struct nhlfe_entry *nh1, *nh2;
struct nhlfe_key *key1, *key2;
int ret;
nh1 = (struct nhlfe_entry *) data1;
nh2 = (struct nhlfe_entry *) data2;
key1 = (struct nhlfe_key *) nh1->nkey;
key2 = (struct nhlfe_key *) nh2->nkey;
ret = memcmp (&key1->nh_addr, &key2->nh_addr, sizeof (struct in_addr));
if (ret != 0)
return ret;
if (key1->oif_ix > key2->oif_ix)
return 1;
else if (key1->oif_ix < key2->oif_ix)
return -1;
if (key1->out_label > key2->out_label)
return 1;
else if (key1->out_label < key2->out_label)
return -1;
return 0;
}
现在,我要做的是添加对多个下一跳的支持,即 我在nhlfe_entry中添加了一个链表:
struct nhlfe_entry
{
u_int32_t nhlfe_ix;
u_char opcode;
...
struct list *nhkey_list;
}
每个'struct list'都是struct listnode,它嵌入了'void * data'指针 调用者的私人数据,这是'struct nhlfe_key'。
所以我的问题是 - 如何基于多个元素生成密钥 列表存储/搜索树中的节点(因为否则现在在 引入列表时,将无法仅基于 one 创建密钥 下一跳地址)。他们也是同样的问题 适用于搜索。
此外,在列表中添加新节点后,是否需要重新构建树, 因为我认为这个操作会改变密钥,因此树可以 变得不平衡? (或AVL树自然正确实现 不需要重建?)
我正在考虑在每个listnode上生成CRC然后总结。这可以保证钥匙的唯一性吗? (缺点是每当我添加/删除listnode时,我必须重新生成密钥,从tre中删除节点并使用新密钥重新添加)。
谢谢!
答案 0 :(得分:2)
我有一个大型系统使用AVL树来快速搜索IP地址:
对于大量IP地址,您通常需要基数树。二叉树将起作用,但您无法使用其前缀存储地址范围,例如10.*
。如果您没有将此用于类似路由的任何内容,或者您不需要节省将整个子网映射到某些内容的空间。
所以我的问题是 - 如何基于列表中的多个元素生成密钥以在树中存储/搜索节点(因为否则现在在引入列表之后,将无法拥有密钥仅基于一个下一跳地址)。此外,他们同样的问题适用于搜索。
您的mpls_cmp_nhlfe_ipv4_key
函数只需比较可能是地址列表的键。显然,(1 2 3)
比较等于(1 2 3)
。此外,(1 2 3)
的比较大于(1 2)
,但小于(1 3)
或(1 2 4)
。
此外,在列表中添加新节点后,是否需要重新构建树...
如果要更新平衡搜索树中的节点以使密钥更改,则最好的办法是将其删除并重新插入。
可能有一些方法可以优化它。例如,假设一个键发生了变化,但是它仍然在树中具有完全相同的后继者和前身。在这种情况下,它可以就地完成。或者密钥可以以这样的方式改变,即节点只需要与前任或后继者交换。在尝试这样的技巧之前我会做对的。
[CRC]可以保证密钥的唯一性吗?
不,CRC是散列函数。它比被散列的对象具有更少的位,因此多个对象可以散列到相同的CRC。 (例外情况是当找到一组元素的“完美散列函数”时,动态数据很少发生这种情况:对某些静态数据集合设计了完美的散列函数。)使用散列方法,你可能会好好用哈希表。 CRC的排序关系可能毫无意义。当必须通过键上的排序关系对集合进行排序时,使用二进制搜索树。