红黑树可以说是程序员经常遇到的一种数据结构,不管是工作还是面试都会涉及,有时候还会让你写一段红黑树代码。

本文主要是讲Linux中的红黑树,关于红黑树定义参考wiki:https://en.wikipedia.org/wiki/Red%E2%80%93black_tree

其中《算法导论》中的定义最为清晰:

红黑树图示:

Linux中的红黑树(rbtree)

下面是我翻译的参考Linux内核文档,https://www.kernel.org/doc/Documentation/rbtree.txt

英文作者:Rob Landley <rob@landley.net>

什么是红黑树,它适用于什么?
------------------------------------------------

红黑树是一种自平衡二叉搜索树,用于存储可排序的键/值数据对。

它不同于基数树(用来有效地存储稀疏数组,因此使用长整数索来插入/存取/删除节点)
和哈希表(它不用进行排序就可以很容易地按序遍历,但必须设定具体大小和散列函数,而红黑树优雅的扩展存储任意键)

红黑树类似于AVL树,但提供更快的实时有界插入和删除,最坏的情况表现是三次旋转(插入仅需2次),虽然查找略慢略慢但是时间仍然在O(log n)以内。

引用Linux Weekly News:

内核中很多地方使用红黑树:
    deadline和CFQ I/O调度程序使用rbtree跟踪请求; CD/DVD块数据驱动器也是如此。
    高分辨率计时器代码使用rbtree来组织计时器请求。
    Ext3文件系统使用rbtree跟踪目录项。
    虚拟存储区(VMA)的跟踪,以及epoll的文件描述符,加密密钥,“分层令牌桶”调度网络数据包也有rbtree的使用。

本文档介绍了Linux rbtree实现的使用。
更多有关红黑树性质和使用的信息,
请参阅:关于红黑树的Linux Weekly News文章
http://lwn.net/Articles/184495/

维基百科在红黑树上的条目
http://en.wikipedia.org/wiki/Red-black_tree

Linux实现红黑树
---------------------------------------

Linux的rbtree实现

存在于文件“lib/rbtree.c”中,要使用头文件“#include <linux/rbtree.h>”。
linux\lib\rbtree.c
linux\include\linux\rbtree.h

文末有rbtree.c和rbtree.h的源码

Linux rbtree在实现上针对速度进行了优化,用户需要编写自己的树搜索和插入函数调用内核提供的rbtree。

创建一个新的rbtree
---------------------

rbtree树中的数据节点是包含struct rb_node成员的结构:

 struct mytype {struct rb_node node;char * keystring;};

当处理嵌入式struct rb_node的指针时,包含数据可以使用标准的container_of()宏访问结构。
此外,可以通过rb_entry(节点,类型,成员)直接访问各个成员。

每个rbtree的根是一个rb_root结构,它被初始化为:struct rb_root mytree = RB_ROOT;

在rbtree中搜索值
----------------------------------

为您的树编写搜索功能非常简单:从root开始比较每个值,并根据需要进入左或右分支。

例如:

struct mytype *my_search(struct rb_root *root, char *string){struct rb_node *node = root->rb_node;while (node) {struct mytype *data = container_of(node, struct mytype, node);int result;result = strcmp(string, data->keystring);if (result < 0)node = node->rb_left;else if (result > 0)node = node->rb_right;elsereturn data;}return NULL;}

将数据插入rbtree
-----------------------------

在树中插入数据涉及首先搜索要插入的位置新节点,然后插入节点并重新平衡(“重新着色”)树。

插入的搜索与先前的搜索不同,找到了指针的位置,用于移植新节点。
新节点也需要指向其父节点的链接以进行重新平衡。

例如:

int my_insert(struct rb_root *root, struct mytype *data){struct rb_node **new = &(root->rb_node), *parent = NULL;/* Figure out where to put new node */while (*new) {struct mytype *this = container_of(*new, struct mytype, node);int result = strcmp(data->keystring, this->keystring);parent = *new;if (result < 0)new = &((*new)->rb_left);else if (result > 0)new = &((*new)->rb_right);elsereturn FALSE;}/* Add new node and rebalance tree. */rb_link_node(&data->node, parent, new);rb_insert_color(&data->node, root);return TRUE;}

删除或替换rbtree中的现有数据
------------------------------------------------

要从树中删除现有节点,请调用:

void rb_erase(struct rb_node * victim,struct rb_root * tree);

例如:

struct mytype *data = mysearch(&mytree, "walrus");if (data) {rb_erase(&data->node, &mytree);myfree(data);}

要使用具有相同键的新节点替换树中的现有节点,请调用:

void rb_replace_node(struct rb_node * old,struct rb_node * new,struct rb_root * tree);

以这种方式替换节点不会对树重新排序:如果新节点不重新排序与旧节点具有相同的key,rbtree可能会损坏。

迭代存储在rbtree中的元素(按排序顺序)
-------------------------------------------------- ----------------

提供了四个函数用来迭代rbtree的内容排序顺序。

这些工作在任意树上,不应该是修改或包装(锁用途除外):

struct rb_node *rb_first(struct rb_root *tree);
struct rb_node *rb_last(struct rb_root *tree);
struct rb_node *rb_next(struct rb_node *node);
struct rb_node *rb_prev(struct rb_node *node);

要开始迭代,请使用指向根的指针调用树的rb_first()或rb_last(),将返回树中的指向包含在其中的节点结构的第一个或最后一个元素指针。
要继续,通过在当前节点上调用rb_next()或rb_prev()来获取下一个或上一个节点。
如果没有剩余节点时返回为NULL。

迭代器函数返回一个指向嵌入式struct rb_node的指针。
可以使用container_of()访问包含数据结构宏,可以通过直接访问个人成员rb_entry(节点,类型,成员)。

例如:

struct rb_node *node;for (node = rb_first(&mytree);node;node = rb_next(node))printk("key=%s\n",rb_entry(node,struct mytype,node)->keystring);

缓存的rbtrees
--------------

计算最左边(最小)的节点是二叉搜索树的一个常见任务。

为此,用户可以使用'struct rb_root_cached'优化O(logN) rb_first()调用避免可能很昂贵的树迭代。
虽然内存占用更大,在可忽略的运行时完成维护开销。

与rb_root结构类似,缓存的rbtree被初始化为:

struct rb_root_cached mytree = RB_ROOT_CACHED;

缓存的rbtree只是一个常规的rb_root,带有一个额外的指针来缓存它最左边的节点。
这允许rb_root_cached存在于rb_root所在的任何地方,
它允许支持增强树以及仅额外的一些接口:

struct rb_node * rb_first_cached(struct rb_root_cached * tree);
void rb_insert_color_cached(struct rb_node *,struct rb_root_cached *,bool);
void rb_erase_cached(struct rb_node * node,struct rb_root_cached *);

插入和删除调用都有各自的增强对应树:

void rb_insert_augmented_cached(struct rb_node * node,struct rb_root_cached *,bool,struct rb_augment_callbacks *);
void rb_erase_augmented_cached(struct rb_node *,struct rb_root_cached *,struct rb_augment_callbacks *);

支持增强rbtrees
-----------------------------

增强的rbtree是一个rbtree,其中存储了每个节点的“一些”附加数据,其中节点N的附加数据必须是函数子树中所有节点的内容都以N为根。
这个数据可以用于增加rbtree的一些新功能。
增强的rbtree是基于基本rbtree基础结构构建的可选功能。
想要此功能的rbtree用户必须调用增强功能函数与用户在插入时提供了扩充回调和删除节点。

实现增强型rbtree操作的C文件必须包含<linux/rbtree_augmented.h>而不是<linux/rbtree.h>。
注意linux/rbtree_augmented.h公开了一些你不应该依赖的rbtree实现细节;
请坚持使用已记录的API,那里并没有包含头文件中的<linux/rbtree_augmented.h>。
这样的实施细节要么是为了尽量减少用户不小心依赖的机会。

在插入时,用户必须更新路径上的增强信息到插入的节点,然后像往常一样调用rb_link_node()和rb_augment_inserted()代替rb_insert_color()调用。
如果rb_augment_inserted()重新平衡rbtree,它将回调到用户提供的功能来在受影响的子树上更新增强信息。

删除节点时,用户必须调用rb_erase_augmented()而不是rb_erase()。
rb_erase_augmented()回调用户提供的函数更新受影响子树的增强信息。

在这两种情况下,回调都是通过struct rb_augment_callbacks提供的。
必须定义3个回调:

- 传播回调,它更新给定的增强值节点及其祖先,直到给定的停止点(或一直到根更新为NULL)。

- 复制回调,复制给定子树的增强值到新分配的子树根。

- 树旋转回调,复制给定的增强值子树到新分配的子树根并重新计算扩充前子树根的信息。

rb_erase_augmented()的编译代码可以内联传播和复制回调,这导致一个大的函数,所以每个增强rbtree用户应该有一个rb_erase_augmented()调用节点以限制编译代码大小。

样例用法
^^^^^^^^^^^^

区间树是增强的rb树的示例,参考《算法导论》。

经典rbtree只有一个key,不能直接用于存储区间范围如[lo:hi],并快速查找任何重叠新的lo:hi:或者找到与一个新的lo:hi是否完全匹配。

但是,可以扩展rbtree以在结构化中存储这样的间隔范围,这样就可以进行有效的查找和完全匹配。

存储在每个节点中的这个“额外信息”是最大的hi(max_hi)作为其后代的所有节点中的值。
这个只需要查看节点,就可以在每个节点上维护信息及其直系子节点。
这将用于O(log n)查找最低匹配(所有可能匹配中的最低起始地址)。

struct interval_tree_node *interval_tree_first_match(struct rb_root *root,unsigned long start, unsigned long last){struct interval_tree_node *node;if (!root->rb_node)return NULL;node = rb_entry(root->rb_node, struct interval_tree_node, rb);while (true) {if (node->rb.rb_left) {struct interval_tree_node *left =rb_entry(node->rb.rb_left,struct interval_tree_node, rb);if (left->__subtree_last >= start) {/** Some nodes in left subtree satisfy Cond2.* Iterate to find the leftmost such node N.* If it also satisfies Cond1, that's the match* we are looking for. Otherwise, there is no* matching interval as nodes to the right of N* can't satisfy Cond1 either.*/node = left;continue;}}if (node->start <= last) {       /* Cond1 */if (node->last >= start)  /* Cond2 */return node; /* node is leftmost match */if (node->rb.rb_right) {node = rb_entry(node->rb.rb_right,struct interval_tree_node, rb);if (node->__subtree_last >= start)continue;}}return NULL;    /* No match */}}

使用以下扩充回调定义插入/删除:

static inline unsigned longcompute_subtree_last(struct interval_tree_node *node){unsigned long max = node->last, subtree_last;if (node->rb.rb_left) {subtree_last = rb_entry(node->rb.rb_left,struct interval_tree_node, rb)->__subtree_last;if (max < subtree_last)max = subtree_last;}if (node->rb.rb_right) {subtree_last = rb_entry(node->rb.rb_right,struct interval_tree_node, rb)->__subtree_last;if (max < subtree_last)max = subtree_last;}return max;}static void augment_propagate(struct rb_node *rb, struct rb_node *stop){while (rb != stop) {struct interval_tree_node *node =rb_entry(rb, struct interval_tree_node, rb);unsigned long subtree_last = compute_subtree_last(node);if (node->__subtree_last == subtree_last)break;node->__subtree_last = subtree_last;rb = rb_parent(&node->rb);}}static void augment_copy(struct rb_node *rb_old, struct rb_node *rb_new){struct interval_tree_node *old =rb_entry(rb_old, struct interval_tree_node, rb);struct interval_tree_node *new =rb_entry(rb_new, struct interval_tree_node, rb);new->__subtree_last = old->__subtree_last;}static void augment_rotate(struct rb_node *rb_old, struct rb_node *rb_new){struct interval_tree_node *old =rb_entry(rb_old, struct interval_tree_node, rb);struct interval_tree_node *new =rb_entry(rb_new, struct interval_tree_node, rb);new->__subtree_last = old->__subtree_last;old->__subtree_last = compute_subtree_last(old);}static const struct rb_augment_callbacks augment_callbacks = {augment_propagate, augment_copy, augment_rotate};void interval_tree_insert(struct interval_tree_node *node,struct rb_root *root){struct rb_node **link = &root->rb_node, *rb_parent = NULL;unsigned long start = node->start, last = node->last;struct interval_tree_node *parent;while (*link) {rb_parent = *link;parent = rb_entry(rb_parent, struct interval_tree_node, rb);if (parent->__subtree_last < last)parent->__subtree_last = last;if (start < parent->start)link = &parent->rb.rb_left;elselink = &parent->rb.rb_right;}node->__subtree_last = last;rb_link_node(&node->rb, rb_parent, link);rb_insert_augmented(&node->rb, root, &augment_callbacks);}void interval_tree_remove(struct interval_tree_node *node,struct rb_root *root){rb_erase_augmented(&node->rb, root, &augment_callbacks);}

下面是内核的rbtree源码:

/*Red Black Trees(C) 1999  Andrea Arcangeli <andrea@suse.de>This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USAlinux/include/linux/rbtree.hTo use rbtrees you'll have to implement your own insert and search cores.This will avoid us to use callbacks and to drop drammatically performances.I know it's not the cleaner way,  but in C (not in C++) to getperformances and genericity...Some example of insert and search follows here. The search is a plainnormal search over an ordered tree. The insert instead must be implementedint two steps: as first thing the code must insert the element inorder as a red leaf in the tree, then the support library functionrb_insert_color() must be called. Such function will do thenot trivial work to rebalance the rbtree if necessary.-----------------------------------------------------------------------
static inline struct page * rb_search_page_cache(struct inode * inode,unsigned long offset)
{struct rb_node * n = inode->i_rb_page_cache.rb_node;struct page * page;while (n){page = rb_entry(n, struct page, rb_page_cache);if (offset < page->offset)n = n->rb_left;else if (offset > page->offset)n = n->rb_right;elsereturn page;}return NULL;
}static inline struct page * __rb_insert_page_cache(struct inode * inode,unsigned long offset,struct rb_node * node)
{struct rb_node ** p = &inode->i_rb_page_cache.rb_node;struct rb_node * parent = NULL;struct page * page;while (*p){parent = *p;page = rb_entry(parent, struct page, rb_page_cache);if (offset < page->offset)p = &(*p)->rb_left;else if (offset > page->offset)p = &(*p)->rb_right;elsereturn page;}rb_link_node(node, parent, p);return NULL;
}static inline struct page * rb_insert_page_cache(struct inode * inode,unsigned long offset,struct rb_node * node)
{struct page * ret;if ((ret = __rb_insert_page_cache(inode, offset, node)))goto out;rb_insert_color(node, &inode->i_rb_page_cache);out:return ret;
}
-----------------------------------------------------------------------
*/#ifndef   _LINUX_RBTREE_H
#define _LINUX_RBTREE_H#include <linux/kernel.h>
#include <linux/stddef.h>struct rb_node
{unsigned long  rb_parent_color;
#define RB_RED      0
#define RB_BLACK    1struct rb_node *rb_right;struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));/* The alignment might seem pointless, but allegedly CRIS needs it */struct rb_root
{struct rb_node *rb_node;
};#define rb_parent(r)   ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r)   ((r)->rb_parent_color & 1)
#define rb_is_red(r)   (!rb_color(r))
#define rb_is_black(r) rb_color(r)
#define rb_set_red(r)  do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r)  do { (r)->rb_parent_color |= 1; } while (0)static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}#define RB_ROOT    (struct rb_root) { NULL, }
#define rb_entry(ptr, type, member) container_of(ptr, type, member)#define RB_EMPTY_ROOT(root)  ((root)->rb_node == NULL)
#define RB_EMPTY_NODE(node) (rb_parent(node) == node)
#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))extern void rb_insert_color(struct rb_node *, struct rb_root *);
extern void rb_erase(struct rb_node *, struct rb_root *);/* Find logical next and previous nodes in a tree */
extern struct rb_node *rb_next(const struct rb_node *);
extern struct rb_node *rb_prev(const struct rb_node *);
extern struct rb_node *rb_first(const struct rb_root *);
extern struct rb_node *rb_last(const struct rb_root *);/* Fast replacement of a single node without remove/rebalance/add/rebalance */
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root);static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,struct rb_node ** rb_link)
{node->rb_parent_color = (unsigned long )parent;node->rb_left = node->rb_right = NULL;*rb_link = node;
}#endif /* _LINUX_RBTREE_H */
/*Red Black Trees(C) 1999  Andrea Arcangeli <andrea@suse.de>(C) 2002  David Woodhouse <dwmw2@infradead.org>This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USAlinux/lib/rbtree.c
*/#include <linux/rbtree.h>
#include <linux/module.h>static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
{struct rb_node *right = node->rb_right;struct rb_node *parent = rb_parent(node);if ((node->rb_right = right->rb_left))rb_set_parent(right->rb_left, node);right->rb_left = node;rb_set_parent(right, parent);if (parent){if (node == parent->rb_left)parent->rb_left = right;elseparent->rb_right = right;}elseroot->rb_node = right;rb_set_parent(node, right);
}static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
{struct rb_node *left = node->rb_left;struct rb_node *parent = rb_parent(node);if ((node->rb_left = left->rb_right))rb_set_parent(left->rb_right, node);left->rb_right = node;rb_set_parent(left, parent);if (parent){if (node == parent->rb_right)parent->rb_right = left;elseparent->rb_left = left;}elseroot->rb_node = left;rb_set_parent(node, left);
}void rb_insert_color(struct rb_node *node, struct rb_root *root)
{struct rb_node *parent, *gparent;while ((parent = rb_parent(node)) && rb_is_red(parent)){gparent = rb_parent(parent);if (parent == gparent->rb_left){{register struct rb_node *uncle = gparent->rb_right;if (uncle && rb_is_red(uncle)){rb_set_black(uncle);rb_set_black(parent);rb_set_red(gparent);node = gparent;continue;}}if (parent->rb_right == node){register struct rb_node *tmp;__rb_rotate_left(parent, root);tmp = parent;parent = node;node = tmp;}rb_set_black(parent);rb_set_red(gparent);__rb_rotate_right(gparent, root);} else {{register struct rb_node *uncle = gparent->rb_left;if (uncle && rb_is_red(uncle)){rb_set_black(uncle);rb_set_black(parent);rb_set_red(gparent);node = gparent;continue;}}if (parent->rb_left == node){register struct rb_node *tmp;__rb_rotate_right(parent, root);tmp = parent;parent = node;node = tmp;}rb_set_black(parent);rb_set_red(gparent);__rb_rotate_left(gparent, root);}}rb_set_black(root->rb_node);
}
EXPORT_SYMBOL(rb_insert_color);static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,struct rb_root *root)
{struct rb_node *other;while ((!node || rb_is_black(node)) && node != root->rb_node){if (parent->rb_left == node){other = parent->rb_right;if (rb_is_red(other)){rb_set_black(other);rb_set_red(parent);__rb_rotate_left(parent, root);other = parent->rb_right;}if ((!other->rb_left || rb_is_black(other->rb_left)) &&(!other->rb_right || rb_is_black(other->rb_right))){rb_set_red(other);node = parent;parent = rb_parent(node);}else{if (!other->rb_right || rb_is_black(other->rb_right)){rb_set_black(other->rb_left);rb_set_red(other);__rb_rotate_right(other, root);other = parent->rb_right;}rb_set_color(other, rb_color(parent));rb_set_black(parent);rb_set_black(other->rb_right);__rb_rotate_left(parent, root);node = root->rb_node;break;}}else{other = parent->rb_left;if (rb_is_red(other)){rb_set_black(other);rb_set_red(parent);__rb_rotate_right(parent, root);other = parent->rb_left;}if ((!other->rb_left || rb_is_black(other->rb_left)) &&(!other->rb_right || rb_is_black(other->rb_right))){rb_set_red(other);node = parent;parent = rb_parent(node);}else{if (!other->rb_left || rb_is_black(other->rb_left)){rb_set_black(other->rb_right);rb_set_red(other);__rb_rotate_left(other, root);other = parent->rb_left;}rb_set_color(other, rb_color(parent));rb_set_black(parent);rb_set_black(other->rb_left);__rb_rotate_right(parent, root);node = root->rb_node;break;}}}if (node)rb_set_black(node);
}void rb_erase(struct rb_node *node, struct rb_root *root)
{struct rb_node *child, *parent;int color;if (!node->rb_left)child = node->rb_right;else if (!node->rb_right)child = node->rb_left;else{struct rb_node *old = node, *left;node = node->rb_right;while ((left = node->rb_left) != NULL)node = left;if (rb_parent(old)) {if (rb_parent(old)->rb_left == old)rb_parent(old)->rb_left = node;elserb_parent(old)->rb_right = node;} elseroot->rb_node = node;child = node->rb_right;parent = rb_parent(node);color = rb_color(node);if (parent == old) {parent = node;} else {if (child)rb_set_parent(child, parent);parent->rb_left = child;node->rb_right = old->rb_right;rb_set_parent(old->rb_right, node);}node->rb_parent_color = old->rb_parent_color;node->rb_left = old->rb_left;rb_set_parent(old->rb_left, node);goto color;}parent = rb_parent(node);color = rb_color(node);if (child)rb_set_parent(child, parent);if (parent){if (parent->rb_left == node)parent->rb_left = child;elseparent->rb_right = child;}elseroot->rb_node = child;color:if (color == RB_BLACK)__rb_erase_color(child, parent, root);
}
EXPORT_SYMBOL(rb_erase);/** This function returns the first node (in sort order) of the tree.*/
struct rb_node *rb_first(const struct rb_root *root)
{struct rb_node *n;n = root->rb_node;if (!n)return NULL;while (n->rb_left)n = n->rb_left;return n;
}
EXPORT_SYMBOL(rb_first);struct rb_node *rb_last(const struct rb_root *root)
{struct rb_node *n;n = root->rb_node;if (!n)return NULL;while (n->rb_right)n = n->rb_right;return n;
}
EXPORT_SYMBOL(rb_last);struct rb_node *rb_next(const struct rb_node *node)
{struct rb_node *parent;if (rb_parent(node) == node)return NULL;/* If we have a right-hand child, go down and then left as faras we can. */if (node->rb_right) {node = node->rb_right; while (node->rb_left)node=node->rb_left;return (struct rb_node *)node;}/* No right-hand children.  Everything down and left issmaller than us, so any 'next' node must be in the generaldirection of our parent. Go up the tree; any time theancestor is a right-hand child of its parent, keep goingup. First time it's a left-hand child of its parent, saidparent is our 'next' node. */while ((parent = rb_parent(node)) && node == parent->rb_right)node = parent;return parent;
}
EXPORT_SYMBOL(rb_next);struct rb_node *rb_prev(const struct rb_node *node)
{struct rb_node *parent;if (rb_parent(node) == node)return NULL;/* If we have a left-hand child, go down and then right as faras we can. */if (node->rb_left) {node = node->rb_left; while (node->rb_right)node=node->rb_right;return (struct rb_node *)node;}/* No left-hand children. Go up till we find an ancestor whichis a right-hand child of its parent */while ((parent = rb_parent(node)) && node == parent->rb_left)node = parent;return parent;
}
EXPORT_SYMBOL(rb_prev);void rb_replace_node(struct rb_node *victim, struct rb_node *new,struct rb_root *root)
{struct rb_node *parent = rb_parent(victim);/* Set the surrounding nodes to point to the replacement */if (parent) {if (victim == parent->rb_left)parent->rb_left = new;elseparent->rb_right = new;} else {root->rb_node = new;}if (victim->rb_left)rb_set_parent(victim->rb_left, new);if (victim->rb_right)rb_set_parent(victim->rb_right, new);/* Copy the pointers/colour from the victim to the replacement */*new = *victim;
}
EXPORT_SYMBOL(rb_replace_node);

Linux内核的红黑树源码实现以及调用相关推荐

  1. 详解5种红黑树的场景,从Linux内核谈到Nginx源码,听完醍醐灌顶丨Linux服务器开发丨Linux后端开发

    5种红黑树的场景,从Linux内核谈到Nginx源码,听完醍醐灌顶 1. 进程调度CFS的红黑树场景 2. 虚拟内存管理的红黑树场景 3. 共享内存slab的红黑树场景 视频讲解如下,点击观看: [干 ...

  2. linux内核的红黑树

    linux内核的红黑树 很多博文都介绍过红黑树,linux内核对红黑树的实现无疑是经典中的经典,那么就来看看这经典中的经典是怎么样的. 1. 回忆树的基本知识 什么是树,有很多博文中会罗列几条规则,满 ...

  3. 【Linux 内核 内存管理】Linux 内核堆内存管理 ③ ( CPU 计数器瓶颈 | per-CPU 计数器 | Linux 内核 percpu_counter 结构体源码 )

    文章目录 一.CPU 计数器瓶颈 二.per-CPU 计数器及 percpu_counter 结构体源码 一.CPU 计数器瓶颈 如果 操作系统 中有 多个 CPU , 假设只有一个 CPU 计数器工 ...

  4. NGINX下的红黑树源码详解(附 流程图和GIF)

    之前博主稍微讲解了下红黑树的原理,那么在这篇博客博主想要把红黑树讲的更加的透彻,以便于更多的人了解红黑树 (本博客会更加详细的介绍之前的博客没介绍到的,所以各位看官不同再回去翻看博主之前那篇红黑树的原 ...

  5. 红黑树源码及错误解析

    /* 作者:田帅 学校:**大学 版本:红黑树初始版本 */ #include"stdio.h" #include"malloc.h" #define MIN ...

  6. 红黑树java源代码分析_JAVA 红黑树源码

    class RBTree>{ private static final String RedColor = "red"; private static final Strin ...

  7. linux 内核字符驱动char_dev源码分析

    内核模块中字符驱动代码写的相当精简,提供了字符驱动的各种管理功能主要代码位于fs\char_dev.c文件中,分析该模块代码可以主要从三个方面入手: 字符设备号管理:主要提供设备号注册申请等功能 st ...

  8. 使用CUrl断点续传下载Linux内核5.6.2源码

    首先进入Linux的祖宗网站:如下图:www.kernel.org: 看一下当前最新版本为5.6.2:最早可以看到版本3.16.82:再早似乎一时找不到:下载: 非常慢:此网站下载人巨多: 它还有几个 ...

  9. 鸿蒙OS内核分析|解读鸿蒙源码

    操作系统(Operating System): 操作系统的功能是负责管理各种硬件设备,同时对底层硬件设备进行抽象,为上层软件提供高效的系统接口.操作系统设计和实现的优劣直接决定了系统栈的各个方面,比如 ...

最新文章

  1. 计算机硬件的组装实践,毕业论文-计算机硬件组装实践.doc
  2. 阿里 双11 同款,流量防卫兵 Sentinel go 源码解读
  3. python怎么写手机按钮_python与mel的button写法
  4. 你未必知道的49个CSS知识点
  5. 8086微型计算机原理答案,8086微型计算机原理与应用(吴宁)习题答案(第三章)
  6. 无法在只读编辑器中编辑_Mol Plant中国农科院作物科学研究所夏兰琴课题组成功利用 优化的引导基因编辑器在水稻中实现高效精准基因编辑...
  7. linux 路径结构
  8. android o 编译及运行,【转】实践最有效的提高Android Studio运行、编译速度方案
  9. 虚拟机下给Ubuntu挂载新硬盘
  10. php api框架 登录验证码,thinkphp3.2 框架如何使用验证码
  11. 如何在ps添加箭头_PS里怎么画箭头?PS画箭头三种方法介绍
  12. 图片放大后怎么把图片变清晰?
  13. 探索GIS+物联网应用场景 MapGIS IoT实时大数据解决方案
  14. 消防应急疏散指示系统在学校项目上的应用
  15. 09组团队项目-Beta冲刺-5/5
  16. Javaweb项目报告
  17. eplan php文件夹,EPLAN P8 导入部件库的方法-mdb文件
  18. 中职教资证计算机应用,中职计算机教师资格证只能教中职学校的吗
  19. Cypher查询语言--Neo4j中的SQL(6)
  20. SQL注入与万能密码登录

热门文章

  1. 瘦身,优化?分享建站过程中的些许心得
  2. 数商云:聚焦供应链布局,新能源汽车企业重塑产业核心竞争力
  3. 解决${pageContext.request.contextPath }无效问题
  4. Linux操作系统-标准IO库(1)
  5. Nagios监控DELL服务器硬件
  6. PCB线路板蛇形布线要注意哪些问题?
  7. loc和iloc用法辨析
  8. C语言中的文件操作那些事儿~~
  9. 重绘MenuStrip 控件
  10. 关键词爬虫,Python花瓣画板关键词采集存储数据库