应用层使用内核红黑树
内核中的rbtree.c、rbtree.h
红黑树的接口函数中需要编写search和insert两个函数。(详见下面接口函数)
红黑树和hash表
使用红黑树的使用场景我是与hash进行对比的。
-
速度对比
红黑树深度不深的情况下查找速度相差不大;
总体来说哈希表比红黑树要快。 -
数据大小
如果数据大小已知,可以提前规划,hash表可以了
数据不知道多少,红黑树比较好,linux的epoll就是使用的红黑树。 -
内存消耗
嵌入式中对内存比较严格,使用红黑树;如果空间足够使用hash。hash表需要足够大,减少冲突。 -
如果hash 冲突list中元素过多,冲突list可以使用红黑树。
红黑树接口
- 创建一个红黑树
typedef struct tag_tcp_cu_client
{
rb_node_t tree_node;
int32_t cu_sock;
uint8_t dev_id; //为key
} tcp_cu_client_t;
active_node_root = RB_ROOT;
- 插入数据
static int32_t active_node_insert(tcp_cu_client_t *active_new, rb_root_t *root)
{
int32_t result = 0;
rb_node_t **new = &(root->rb_node);
rb_node_t *parent = NULL;
tcp_cu_client_t *active_node = NULL;
while (*new)
{
parent = *new;
active_node = rb_entry(*new, tcp_cu_client_t, tree_node);
result = active_node_key_cmp(&active_new->dev_id, &active_node->dev_id);
if (result < 0)
{
new = &((*new)->rb_left);
}
else if (result > 0)
{
new = &((*new)->rb_right);
}
else
{
return -1;
}
}
/* Add new node and rebalance tree. */
rb_link_node(&active_new->tree_node, parent, new);
rb_insert_color(&active_new->tree_node, root);
return 0;
}
3) 搜索数据
static tcp_cu_client_t *active_node_search(rb_root_t *root, uint8_t *key)
{
int32_t result = 0;
tcp_cu_client_t *active_node = NULL;
rb_node_t *node = root->rb_node;
while (node)
{
active_node = rb_entry(node, tcp_cu_client_t, tree_node);
result = active_node_key_cmp(key, &active_node->dev_id);
if (result < 0)
{
node = node->rb_left;
}
else if (result > 0)
{
node = node->rb_right;
}
else
{
return active_node;
}
}
return NULL;
}
4) 删除数据
int32_t active_node_del(rb_root_t *root,uint8_t dev_id)
{
tcp_cu_client_t *active_node;
active_node = active_node_search(root, &dev_id);
if(active_node != NULL)
{
rb_erase(&active_node->tree_node, root);
free(active_node);
}
return 0;
}
总结
对于工作中常用的算法,数组、链表、hash和树等,分析过一次后,可能不会再考虑算法的实现过程;在实际工作中只会考虑什么环境下使用什么算法,了解他们的区别,性能和缺陷就尤为重要。