Red-black tree es una especie de árbol binario equilibrado. Tiene buenas propiedades. Los nodos del árbol están ordenados y, como está equilibrado, también se busca. No hay una situación muy mala y la complejidad temporal de las operaciones basadas en árboles binarios es O (log (N)). El kernel de Linux usa un árbol rojo-negro para mantener los bloques de memoria al administrar vm_area_struct.
Primero vea include /linux /rbtree.h para ver algunas definiciones de árboles rojo-negros, como sigue:
struct rb_node
{
sin signo long rb_parent_color;
#define RB_RED 0
#define RB_BLACK 1
struct rb_node * rb_right;
struct rb_node * rb_left;
} __attribute __ ((alineado (sizeof (long)))))
struct rb_root es solo un contenedor para struct rb_node * La ventaja es que no parece pasar el puntero secundario. Sí, muy simple. Mira las siguientes macros importantes. Cuidado, encontrarás que rb_parent_color no es tan simple. Andrea Arcangeli usa un pequeño truco aquí, pero es genial. Como su nombre lo indica, este miembro realmente contiene un puntero al padre y el color de este nodo. ¿Cómo lo hizo? Muy simple, la alineación funciona. Dado que es la alineación del tamaño (largo), entonces en el IA-32, los dos bits más bajos de la dirección de cualquier estructura rb_node deben ser cero. En lugar de estar vacío, es mejor usarlos para representar el color. De hecho, uno es suficiente.
De esta forma, para extraer el puntero principal, simplemente borre los dos bits inferiores del miembro rb_parent_color:
#define rb_parent (r) (( Struct rb_node *) ((r) - > rb_parent_color &~ 3))
Para tomar el color, mire el último bit:
# define rb_color (r) ((r) - > rb_parent_color &1)
La prueba de colores y la configuración de colores también es una cuestión de rutina. Se hace mención especial a la siguiente función en línea:
estática en línea void rb_link_node (struct rb_node * node, struct rb_node * parent, struct rb_node ** rb_link);
Establece el padre en el nodo padre del nodo y permite que rb_link apunte al nodo.
Nos centramos en lib /rbtree.c y observamos algunos de los algoritmos importantes asociados con los árboles rojo-negros. Antes de comenzar, recordemos las reglas del árbol rojo-negro:
1. Cada nodo es rojo o negro;
2. El nodo raíz debe ser Negro;
3. Nodos rojos Si los niños tienen hijos, sus hijos deben ser negros;
4. Cada ruta desde el nodo raíz a la hoja debe contener el mismo número de nodos negros. .
Estas cuatro reglas pueden limitar un árbol de clasificación para equilibrarlo.
__rb_rotate_left es una rotación a la izquierda del nodo nodo en el árbol de raíz, y __rb_rotate_right es a la derecha. Estas dos funciones son para servicios posteriores de inserción y eliminación, en lugar de proporcionar una interfaz al exterior.
Los nodos recién insertados se configuran en hojas, teñidas de rojo, si las reglas anteriores se rompen después de la inserción, el color y la rotación se pueden restaurar, y el árbol binario se reequilibra. La función de interfaz para la operación de inserción es
void rb_insert_color (struct rb_node * node, struct rb_root * root);
Coloca el nodo padre determinado El nodo nodo del punto está integrado en el árbol rojo-negro arraigado en la raíz. El análisis del algoritmo específico puede referirse a la Sección 14.3 en [1]. La implementación aquí es casi exactamente la misma que la del libro. La forma de determinar el nodo primario del nodo se debe hacer manualmente llamando a rb_insert_color. Vale la pena señalar que aunque la operación de inserción requiere una iteración de bucle, el número total de rotaciones no excederá dos veces. Así que la eficiencia sigue siendo muy optimista.
La operación de eliminación es más o menos problemática. Primero debe realizar la eliminación y " como el árbol de búsqueda binario normal, y luego juzgar si se debe ejecutar más según el color del nodo eliminado. La operación La interfaz que se eliminará es:
void rb_erase (struct rb_node * node, struct rb_root * root);
De hecho, en realidad no elimina el nodo En su lugar, simplemente deje que se separe del árbol arraigado en la raíz, y finalmente tiene que decidir si llamar a __rb_erase_color para ajustarlo. Para obtener una explicación del algoritmo específico, consulte las Secciones 13.3 y 14.4 de [1], RB-DELETE-FIXUP en el libro correspondiente de __rb_erase_color, y la implementación aquí es básicamente la misma que la del libro.
Las interfaces restantes son más simples.
struct rb_node * rb_first (struct rb_root * root);
Encuentra y devuelve el más pequeño en el árbol rooteado en la raíz Nodo, siempre que vayas desde el nodo raíz a la izquierda.
struct rb_node * rb_last (struct rb_root * root);
es buscar y devolver el más grande, siga hacia la derecha.
struct rb_node * rb_next (struct rb_node * node);
Devolver la sucesión de nodo en el árbol es un poco más complicado. Si el elemento secundario derecho del nodo no está vacío, solo necesita devolver el nodo más pequeño en el subárbol derecho del nodo; si está vacío, debe buscar y encontrar el nodo del elemento secundario izquierdo del padre del nodo superpuesto, regresar Nodo padre Si lo anterior ha alcanzado el nodo raíz, devuelve NULL.
struct rb_node * rb_prev (struct rb_node * node);
Devuelve el precursor del nodo y es simétrico con la operación en rb_next.
void rb_replace_node (struct rb_node * victim, struct rb_node * new, struct rb_root * root);
Reemplace root por root El nodo víctima en el árbol.
Un ejemplo típico de una interfaz de árbol rojo-negro es el siguiente:
página de estructura en línea estática * rb_search_page_cache (struct inode * inode,
desplazamiento largo sin signo)
{
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;
else
return page;
Error de > > load heart_scale al usar el archivo loadASCII El número de columnas en la ter
Este artículo presenta el concepto, la función y el uso de LVM para ayudarlo a comprender LVM y usar
De repente se encontró que el sitio web no se puede abrir, la base de datos muestra que el enlace no
xenserver XenCenter puede vincular tarjetas de red, admite el modo activo-activo y activo-en espera,
Detallado comando de cola de Linux
Resolver la fuente de configuración de Chrome en Linux no es válida
Linux centos apagar y reiniciar comando detallado y combate real
Resuelva la situación donde se desconoce el gráfico en los detalles de Ubuntu
Linux Apache + php + Mysql + cactus 安装 安装
Linux pila del subsistema de barrio (procesos relacionados seis)
Administración y mantenimiento del sistema Linux -df command
Linux enlaces duros y enlaces blandos comprensión profunda
¿Cómo evitar que Win10 Technology Preview se actualice automáticamente?
El archivo abierto de Win8 siempre encontrará la causa de la falta de respuesta y la solución
¿Cómo resolver el problema del código de error de la pantalla azul de inicio de WinXP 0x00000024?
Win8.1Update1 anunció clave de finalización Resumen de información
La función de accesos directos /accesos directos de Windows8
Acerca de la fragmentación de Windows8 Preguntas y respuestas
¿Cómo activar la versión preliminar de Win10 10565? Cómo activar Win10 Build 10565
¿Cómo resolver la pantalla azul causada por el archivo tdx.sys del sistema Win8.1?