Summary
Bowen explores four key points: 1, a brief introduction to the red-black tree; 2, red-Black tree node data structure; 3, the color of the parent pointer field and the node of the red-black tree node are organically combined; 4. Defines the interface between the red-black tree and the operator tree node pointer and node color, including a series of macros and
Note: All code originates from kernel 3.10
Preface
Invoke a part of the <Documentation/rbtree.txt> and do a simple translation (not very good in individual places), just as the opening of the red-black tree blog.
What are red-black trees, and What are for? ------------------------------------------------What is a red-black tree.
And what they are used for. Red-black trees are a type of self-balancing binary search tree, used for storing sortable to key/value data pairs. This is differs from radix trees (which are used to efficiently store sparse arrays and thus with long integer indexes to Inse Rt/access/delete nodes) and hash tables (which are not kept sorted to is easily in order, and traversed is must for
A specific size and hash function where rbtrees scale gracefully storing keys). The red-black tree is a self-balanced binary search tree for storing sortable key/numeric data. It is different from the cardinality tree (used to efficiently store sparse arrays, so using long integers strands insert/access/delete nodes and hash tables (it can easily be sequentially traversed without sorting, but you have to set the specific size and hash function, while the red-black tree gracefully extends the storage of any key) Red-black trees are similar to AVL trees, but provide faster real-time bounded worst case performance for insertion and deletion (at most Two rotations and three rotations, respectively, to balance the "tree" with slightly slower (but still O (log n)) lookup Ti
Me. Red-black trees are similar to AVL trees, but for inserts (up to two rotations) and deletions (up to three rotations to rebalance the red and blackTree) provides faster performance for worst-case real-time complexity, and slightly slower query time (still O (log n)) to quote Linux Weekly News:there are a number of red-black.
In the kernel. The deadline and CFQ I/O schedulers employ rbtrees to track requests;
The packet CD/DVD driver does the same. The high-resolution timer code uses an rbtree to organize outstanding timer requests. The EXT3 filesystem tracks directory entries in a red-black tree. Virtual Memory Areas (VMAs) are tracked with red-black trees, as are epoll file descriptors, cryptographic keys, and N
Etwork packets in the "Hierarchical token bucket" scheduler.
Invoke the Linux Weekly news:deadline and CFQ (completely Fair queueing) Two kinds of I/O dispatch, use the Rbtree tracing request; The same is true for CD/DVD block data drives.
High-resolution timer code using RBTREE Excellent organization timer request. The Ext3 file system uses Rbtree to track directory entries. Virtual Store (VMA) tracking, and Epoll file descriptor, encryption key, "layered token bucket" Scheduling network packets are also used Rbtree.
1, red-black tree node data structure
<linux/rbtree.h>
struct Rb_node {
unsignedlong __rb_parent_color;//below to parse this variable in detail
structrb_ Node *rb_right;//right child pointer field
Structrb_node *rb_left;//left child pointer field
} __attribute__ ((Aligned (sizeof (long)));
--sizeof (long) returns the long-typed number of bytes n;aligned (n)--Indicates the structure body n-byte alignment; __attribute__ is the GCC compiler extension, the property constraint. The meaning of this sentence: struct Rb_node is aligned with 4 bytes (long)! For __attribute__ and aligned details and usage you can access the GCC online user's Manual
The STRUCTRB_NODE structure is 4-byte aligned, then it's in-memory base address base must be a multiple of 4 (base% 4 = 0); Because the pointer occupies 4B above the 32-bit system, the low two bit of base base of 32bit must be 0 (otherwise "base% 4 = 0") Not established, no longer 4B aligned).
Red-black tree nodes must hold four values:
(1) own color (color, red-black tree must)
(2) parent node pointer (makes the red-black tree go up the time complexity of finding the parent node is O (1))
(3) Left child node pointer (make red and black tree left to go to find the time complexity of the left child is O (1))
(4) Right child node pointer (make red black tree to the right to find the time complexity of the right child is O (1))
<linux/augmented.h>
#define rb_red 0
#define rb_black 1
The red and black tree nodes have only two colors-red (0) and Black (1), and 1bit is enough to represent them. and the struct RB_NODE structure base address is low 2 bit "Do not use", then can use the lowest bit to store the color of the node, the base addresses and color values or (|) The operation is integrated into a variable __rb_parent_color, which saves a variable that stores the color.
"If you define a variable to store a color value, assume that 4 b unsigned integer (even if it is a shot or char type that takes up 4B in 4B alignment) then when the number of nodes in the tree grows, each growth of one tree node will cost 4 B more. and store the parent node address of the variable is low two bits and not used, 4 tree nodes waste 1 B; Remember: The core memory is limited, 1B per consumption, the core of less 1b--without loss of performance, can save on savings. 】
2, red and black roots
<linux/rbtree.h>
struct Rb_root {
struct rb_node *rb_node;
};
Whether this pointer is empty determines whether the tree is empty. Introduce the following interface
#define RB_EMPTY_ROOT (Root) ( (root)->rb_node = = NULL)
Defines a red-black tree, initialized to an empty tree:
static struct Rb_root mytree = rb_root;
Where rb_root is defined in <linux/rbtree.h>
#define Rb_root (struct rb_root) {NULL,}
It casts {NULL,} to (struct rb_root) and initializes the tree to null. 3. Interface of manipulating member __rb_parent_color 3.1. Extract parent node address
<linux/rbtree.h>
#define Rb_parent (R) (struct Rb_node *) ((r)->__rb_parent_color & ~3))
<linux/rbtree_augmented.h>
#define __rb_parent (PC) ( struct Rb_node *) (PC & ~3)
32bit
3=0000 0000 0000 0000 0000 0000 0000 0011
~3 = 1111 1111 1111 1111 1111 1111 1111 1100
__rb_parent_color & ~3= Filtered down 2-bit (0 to 0) and retained 第3-32位. Because __rb_parent_color is an unsigned integer, cast to struct rb_node * type.
The above two macro functions are the same, but the parameters are different-the former is a pointer to the node r; the latter is a node member Unsignedlong __rb_parent_color. In addition, the "__" prefix also emphasizes internal and external points.
<lib/rbtree.c>
static inline struct Rb_node *rb_red_parent (struct Rb_node *red)
{return
(struct rb_ Node *) red->__rb_parent_color;
}
Because the Red node's member variable __rb_parent_color two bit is 0, the __rb_parent_color value is the parent node base of this red node. Convert the data type and return directly. 3.2. Extract and judge the color of the knot
<linux/rbtree_augmented.h>
#define __RB_COLOR (PC) & 1 //struct rb_node the lowest bit of the member "PC" value.
#define __RB_IS_BLACK (PC) __rb_color (PC)
//logic to determine if the node is black, the PC value is at least 1, the node is black (true), and the lowest bit is 0, not black (false)
#define __rb_is_red (PC) (!__rb_color (PC))
///logic determines whether the node is red, the minimum digit of the PC is 1, not the red (false), the lowest bit is 0, the red (true)
#define RB_COLOR (RB) __rb_color (RB)->__rb_parent_color)
//Extract node color, value 0 red, value 1 is black;
#define RB_IS_RED (RB) __rb_is_ Red ((RB)->__rb_parent_color)
//encapsulated as an external interface, accept struct rb_node* type RB as parameter
#define RB_IS_BLACK (RB) __rb_ Is_black (RB)->__rb_parent_color)
//encapsulated as external interface, accept struct rb_node* type RB as parameter
3.3, set the parent node pointer
<linux/rbtree_augmented.h>
static inline void rb_set_parent (struct rb_node *rb, struct rb_node *p)
{ C21/>rb->__rb_parent_color = Rb_color (RB) | (unsigned long) p;
}
As can be easily understood by the diagram, this function can be used to update the node's parent pointer so that it points to the new parent node. 3.4, set the parent node pointer and node color
<linux/rbtree_augmented.h>
static inline void Rb_set_parent_color (struct rb_node *rb, struct rb_node *p, int Color)
{
Rb->__rb_parent_color = (unsigned long) p | color;
}
<lib/rbtree.c>
static inline void Rb_set_black (struct rb_node *rb)
{
Rb->__rb_parent_color |= RB _black;
}
3.5, the logical judgment of the node
<linux/rbtree.h>/
* ' empty ' nodes are nodes that are known the not-to is inserted in a rbree * *
comments have been made clear, the code Also very clear. The reason is again later on.
#define RB_EMPTY_NODE (node)
->__rb_parent_color = = (unsigned long) (node)
#define Rb_clear_node (node) \ (
node)->__rb_parent_color = (unsigned long) (node)
4. Extended red and black trees
For operations that extend the red-black tree, you must provide a callback function for the specific action. The core defines a callback function data structure that expands the red-black tree. Consists of three parts: reproduction, copy, rotation.
<linux/rbtree_augmented.h>
struct Rb_augment_callbacks {
void (*propagate) (struct rb_node *node, struct rb_node);
void (*copy) (struct rb_node *old, struct rb_node);
void (*rotate) (struct rb_node *old, struct rb_node);
Static definition extension red-black tree callback function can call the following macro, which defines the corresponding callback function name and body according to the user-supplied parameters.
<linux/rbtree_augmented.h>
#define Rb_declare_callbacks (rbstatic, Rbname, Rbstruct, Rbfield, Rbtype, rbaugmented, rbcompute) \ Static Inli
ne void \ Rbname # _propagate (struct rb_node *rb, struct rb_node *stop) \ {\ while (RB!= stop) {\ Rbstruct *node = Rb_entry (RB, Rbstruct, Rbfield); \ rbtype augmented = rbcompute (node); \ if (node->rbaugmented = = augmented) \ break; \ node->rbaugmented = augmented; RB = Rb_parent (&node->rbfield); \} \ static inline void \ Rbname # _copy (struct rb_node *rb_old, struct rb_node *rb_new) \ { \ rbstruct *old = Rb_entry (Rb_old, rbstruct, Rbfield); \ rbstruct *new = Rb_entry (Rb_new, rbstruct, Rbfield); \ new->rbaugmented = old->rbaugmented; \} \ static void \ Rbname # # _rotate (struct rb_node *rb_old, struct rb_node *rb_new) \ {\ Rbstru CT *old = rb_entry (Rb_old, rbstruct, Rbfield); \ rbstruct *new = Rb_entry (Rb_new, Rbstruct, RBFIeld); \ new->rbaugmented = old->rbaugmented; \ old->rbaugmented = Rbcompute (old); \} \ rbstatic const struct Rb_augment_callbacks rbname = {\ Rbname # _propagate, Rbname # # _copy, Rbname # # _rotate \};
The best way to understand a macro is to set it up in an instance. The following code is an example in <rbtree.txt>
static void Augment_propagate (struct rb_node *rb, struct Rb_node *stop) {while (RB!= stop) {struct Interval_tree_nod
E *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_ent
Ry (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_ent
Ry (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
};
For the operation of the red and black tree, the next blog post gives a detailed explanation.
Statement:
>> knowledge to spread, labor to respect! Benefit from open source, feedback to society! Everybody participates, serves all mankind!
>> this blog by my_live_123 original (HTTP://BLOG.CSDN.NET/CWCMCW), reproduced please specify the source! ^_^