mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 08:44:41 +00:00 
			
		
		
		
	[PATCH] Documentation/rbtree.txt
Documentation for lib/rbtree.c. Signed-off-by: Rob Landley <rob@landley.net> Cc: "Randy.Dunlap" <rdunlap@xenotime.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									82ddcb0405
								
							
						
					
					
						commit
						c742b53114
					
				
					 1 changed files with 192 additions and 0 deletions
				
			
		
							
								
								
									
										192
									
								
								Documentation/rbtree.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								Documentation/rbtree.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,192 @@ | |||
| Red-black Trees (rbtree) in Linux | ||||
| January 18, 2007 | ||||
| Rob Landley <rob@landley.net> | ||||
| ============================= | ||||
| 
 | ||||
| What are red-black trees, and what are they for? | ||||
| ------------------------------------------------ | ||||
| 
 | ||||
| Red-black trees are a type of self-balancing binary search tree, used for | ||||
| storing sortable key/value data pairs.  This differs from radix trees (which | ||||
| are used to efficiently store sparse arrays and thus use long integer indexes | ||||
| to insert/access/delete nodes) and hash tables (which are not kept sorted to | ||||
| be easily traversed in order, and must be tuned for a specific size and | ||||
| hash function where rbtrees scale gracefully storing arbitrary keys). | ||||
| 
 | ||||
| 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 time. | ||||
| 
 | ||||
| To quote Linux Weekly News: | ||||
| 
 | ||||
|     There are a number of red-black trees in use in the kernel. | ||||
|     The anticipatory, deadline, and CFQ I/O schedulers all 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 network | ||||
|     packets in the "hierarchical token bucket" scheduler. | ||||
| 
 | ||||
| This document covers use of the Linux rbtree implementation.  For more | ||||
| information on the nature and implementation of Red Black Trees,  see: | ||||
| 
 | ||||
|   Linux Weekly News article on red-black trees | ||||
|     http://lwn.net/Articles/184495/ | ||||
| 
 | ||||
|   Wikipedia entry on red-black trees | ||||
|     http://en.wikipedia.org/wiki/Red-black_tree | ||||
| 
 | ||||
| Linux implementation of red-black trees | ||||
| --------------------------------------- | ||||
| 
 | ||||
| Linux's rbtree implementation lives in the file "lib/rbtree.c".  To use it, | ||||
| "#include <linux/rbtree.h>". | ||||
| 
 | ||||
| The Linux rbtree implementation is optimized for speed, and thus has one | ||||
| less layer of indirection (and better cache locality) than more traditional | ||||
| tree implementations.  Instead of using pointers to separate rb_node and data | ||||
| structures, each instance of struct rb_node is embedded in the data structure | ||||
| it organizes.  And instead of using a comparison callback function pointer, | ||||
| users are expected to write their own tree search and insert functions | ||||
| which call the provided rbtree functions.  Locking is also left up to the | ||||
| user of the rbtree code. | ||||
| 
 | ||||
| Creating a new rbtree | ||||
| --------------------- | ||||
| 
 | ||||
| Data nodes in an rbtree tree are structures containing a struct rb_node member: | ||||
| 
 | ||||
|   struct mytype { | ||||
|   	struct rb_node node; | ||||
|   	char *keystring; | ||||
|   }; | ||||
| 
 | ||||
| When dealing with a pointer to the embedded struct rb_node, the containing data | ||||
| structure may be accessed with the standard container_of() macro.  In addition, | ||||
| individual members may be accessed directly via rb_entry(node, type, member). | ||||
| 
 | ||||
| At the root of each rbtree is an rb_root structure, which is initialized to be | ||||
| empty via: | ||||
| 
 | ||||
|   struct rb_root mytree = RB_ROOT; | ||||
| 
 | ||||
| Searching for a value in an rbtree | ||||
| ---------------------------------- | ||||
| 
 | ||||
| Writing a search function for your tree is fairly straightforward: start at the | ||||
| root, compare each value, and follow the left or right branch as necessary. | ||||
| 
 | ||||
| Example: | ||||
| 
 | ||||
|   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; | ||||
| 		else | ||||
|   			return data; | ||||
| 	} | ||||
| 	return NULL; | ||||
|   } | ||||
| 
 | ||||
| Inserting data into an rbtree | ||||
| ----------------------------- | ||||
| 
 | ||||
| Inserting data in the tree involves first searching for the place to insert the | ||||
| new node, then inserting the node and rebalancing ("recoloring") the tree. | ||||
| 
 | ||||
| The search for insertion differs from the previous search by finding the | ||||
| location of the pointer on which to graft the new node.  The new node also | ||||
| needs a link to its parent node for rebalancing purposes. | ||||
| 
 | ||||
| Example: | ||||
| 
 | ||||
|   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); | ||||
|   		else | ||||
|   			return FALSE; | ||||
|   	} | ||||
| 
 | ||||
|   	/* Add new node and rebalance tree. */ | ||||
|   	rb_link_node(data->node, parent, new); | ||||
|   	rb_insert_color(data->node, root); | ||||
| 
 | ||||
| 	return TRUE; | ||||
|   } | ||||
| 
 | ||||
| Removing or replacing existing data in an rbtree | ||||
| ------------------------------------------------ | ||||
| 
 | ||||
| To remove an existing node from a tree, call: | ||||
| 
 | ||||
|   void rb_erase(struct rb_node *victim, struct rb_root *tree); | ||||
| 
 | ||||
| Example: | ||||
| 
 | ||||
|   struct mytype *data = mysearch(mytree, "walrus"); | ||||
| 
 | ||||
|   if (data) { | ||||
|   	rb_erase(data->node, mytree); | ||||
|   	myfree(data); | ||||
|   } | ||||
| 
 | ||||
| To replace an existing node in a tree with a new one with the same key, call: | ||||
| 
 | ||||
|   void rb_replace_node(struct rb_node *old, struct rb_node *new, | ||||
|   			struct rb_root *tree); | ||||
| 
 | ||||
| Replacing a node this way does not re-sort the tree: If the new node doesn't | ||||
| have the same key as the old node, the rbtree will probably become corrupted. | ||||
| 
 | ||||
| Iterating through the elements stored in an rbtree (in sort order) | ||||
| ------------------------------------------------------------------ | ||||
| 
 | ||||
| Four functions are provided for iterating through an rbtree's contents in | ||||
| sorted order.  These work on arbitrary trees, and should not need to be | ||||
| modified or wrapped (except for locking purposes): | ||||
| 
 | ||||
|   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); | ||||
| 
 | ||||
| To start iterating, call rb_first() or rb_last() with a pointer to the root | ||||
| of the tree, which will return a pointer to the node structure contained in | ||||
| the first or last element in the tree.  To continue, fetch the next or previous | ||||
| node by calling rb_next() or rb_prev() on the current node.  This will return | ||||
| NULL when there are no more nodes left. | ||||
| 
 | ||||
| The iterator functions return a pointer to the embedded struct rb_node, from | ||||
| which the containing data structure may be accessed with the container_of() | ||||
| macro, and individual members may be accessed directly via | ||||
| rb_entry(node, type, member). | ||||
| 
 | ||||
| Example: | ||||
| 
 | ||||
|   struct rb_node *node; | ||||
|   for (node = rb_first(&mytree); node; node = rb_next(node)) | ||||
|   	printk("key=%s\n", rb_entry(node, int, keystring)); | ||||
| 
 | ||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Rob Landley
						Rob Landley