Arbres de cerca binaris són fonamentals estructura de dades, però el seu rendiment pot patir si l'arbre es desequilibra. Arbres negres vermells són un tipus de arbre de cerca binari equilibrat que utilitzen un conjunt de regles per mantenir l'equilibri, garantint la complexitat del temps logarítmica per a operacions com inserció, supressió i cerca , independentment de la forma inicial de l'arbre. Arbres negres vermells s'autoequilibren, utilitzant un esquema de codificació de colors senzill per ajustar l'arbre després de cada modificació.
Arbre vermell-negre
Taula de contingut
paraula clau estàtica en java
- Què és un arbre vermell-negre?
- Propietats dels arbres vermell-negres
- Exemple d'arbre vermell-negre
- Per què els arbres vermells-negres?
- Comparació amb AVL Tree:
- Punts interessants sobre l'arbre vermell-negre:
- Operacions bàsiques de l'arbre vermell-negre:
- 1. Inserció
- 2. Cercant
- 3. Supressió
- 4. Rotació
- Quan fer les rotacions?
- Implementació de l'arbre vermell-negre:
- Avantatges dels arbres vermells i negres:
- Desavantatges dels arbres vermells i negres:
- Aplicacions dels arbres vermells i negres:
Què és un arbre vermell-negre?
A Arbre vermell-negre és un autoequilibri arbre de cerca binari on cada node té un atribut addicional: un color, que pot ser qualsevol vermell o negre . L'objectiu principal d'aquests arbres és mantenir l'equilibri durant les insercions i les supressions, assegurant una recuperació i manipulació de dades eficients.
Propietats dels arbres vermell-negres
A Arbre vermell-negre tenen les següents propietats:
- Color del node : Cada node és vermell o negre .
- Propietat d'arrel : L'arrel de l'arbre és sempre negre .
- Propietat vermella : els nodes vermells no poden tenir fills vermells (no hi ha dos nodes vermells consecutius en cap camí).
- Propietat Negra : Cada camí des d'un node als seus nodes nuls descendents (fulles) té el mateix nombre de negre nodes.
- Propietat de la fulla : Totes les fulles (nodes NIL) són negre .
Aquestes propietats garanteixen que el camí més llarg des de l'arrel fins a qualsevol fulla no sigui més del doble que el camí més curt, mantenint l'equilibri i el rendiment eficient de l'arbre.
Exemple d'arbre vermell-negre
El Arbre vermell-negre correcte a la imatge de dalt assegura que cada camí des de l'arrel fins a un node fulla tingui el mateix nombre de nodes negres. En aquest cas, n'hi ha un (excepte el node arrel).
El Arbre vermell negre incorrecte no segueix les propietats vermell-negre com dos nodes vermells són adjacents entre si. Un altre problema és que un dels camins cap a un node full té zero nodes negres, mentre que els altres dos contenen un node negre.
Per què els arbres vermells-negres?
La majoria de les operacions de BST (p. ex., cerca, màx., mínim, inserir, suprimir, etc.) O(h) temps on h és l'alçada de la BST . El cost d'aquestes operacions pot arribar a ser O(n) per un esbiaixat Arbre binari. Si ens assegurem que es manté l'alçada de l'arbre O(log n) després de cada inserció i supressió, podem garantir un límit superior de O(log n) per a totes aquestes operacions. L'alçada d'un arbre vermell-negre és sempre O(log n) on n és el nombre de nodes de l'arbre.
Sr. No. | Algoritme | Complexitat temporal |
---|---|---|
1. | Cerca | O(log n) |
2. | Insereix | O(log n) |
3. | Suprimeix | O(log n) |
Comparació amb Arbre AVL :
Els arbres AVL són més equilibrats en comparació amb els arbres vermell-negre, però poden provocar més rotacions durant la inserció i la supressió. Per tant, si la vostra aplicació implica insercions i supressions freqüents, haureu de preferir els arbres vermell-negre. I si les insercions i les supressions són menys freqüents i la cerca és una operació més freqüent, aleshores Arbre AVL s'ha de preferir a l'arbre vermell-negre.
Com garanteix l'equilibri un arbre vermell-negre?
Un exemple senzill per entendre l'equilibri és que una cadena de 3 nodes no és possible a l'arbre vermell-negre. Podem provar qualsevol combinació de colors i veure si tots violen la propietat de l'arbre vermell-negre.

Estructura adequada d'un arbre vermell-negre de tres nusos
c estructura en estructura
Punts interessants sobre l'arbre vermell-negre:
- El negre L'alçada de l'arbre vermell-negre és el nombre de nodes negres en un camí des del node arrel fins a un node fulla. Els nodes de fulla també es compten com a negre nodes. Així doncs, un arbre vermell-negre d'alçada h té alçada negra>= h/2 .
- Alçada d'un arbre vermell-negre amb n nodes és h<= 2 log 2 (n + 1) .
- Totes les fulles (NIL) són negre .
- El negre La profunditat d'un node es defineix com el nombre de nodes negres des de l'arrel fins a aquest node, és a dir, el nombre d'ancestres negres.
Operacions bàsiques de l'arbre vermell-negre:
Les operacions bàsiques en un arbre vermell-negre inclouen:
- Inserció
- Cerca
- Supressió
- Rotació
1. Inserció
La inserció d'un nou node en un arbre vermell-negre implica un procés de dos passos: realitzar un estàndard Inserció de l'arbre de cerca binari (BST). , seguit de la correcció de qualsevol infracció de les propietats vermell-negre.
Passos d'inserció
- Inserció BST : Inseriu el nou node com en un BST estàndard.
- Corregir les infraccions :
- Si el pare del nou node és negre , no s'incompleix cap propietat.
- Si el pare ho és vermell , l'arbre pot infringir la propietat vermella i requereixen correccions.
Correcció de les infraccions durant la inserció
Després d'inserir el nou node com a vermell node, podríem trobar diversos casos depenent dels colors del pare i l'oncle del node (el germà del pare):
- Cas 1: l'oncle és vermell : Recoloreu el pare i l'oncle negre , i l'avi a vermell . A continuació, puja a l'arbre per comprovar si hi ha més violacions.
- Cas 2: L'oncle és negre :
- Subcas 2.1: Node és un fill correcte : Feu una rotació a l'esquerra sobre el pare.
- Subcas 2.2: Node és un fill esquerre : Feu una rotació dreta sobre l'avi i torneu a pintar adequadament.
2. Cercant
Cercar un node en un arbre vermell-negre és similar a cercar en un estàndard Arbre de cerca binari (BST) . L'operació de cerca segueix un camí senzill des de arrel a a full , comparant el valor objectiu amb el valor del node actual i movent-nos cap a l'esquerra o cap a la dreta en conseqüència.
Passos de cerca
- Comenceu a l'arrel : Comenceu la cerca al node arrel.
- Travessa l'Arbre :
- Si el valor objectiu és igual al valor del node actual, es troba el node.
- Si el valor objectiu és inferior al valor del node actual, moveu-vos al fill esquerre.
- Si el valor objectiu és més gran que el valor del node actual, moveu-vos al fill dret.
- Repetiu : Continueu aquest procés fins que es trobi el valor objectiu o s'arribi a un node NIL (indicant que el valor no està present a l'arbre).
3. Supressió
La supressió d'un node d'un arbre vermell-negre també implica un procés de dos passos: realitzar la supressió de BST, seguida de corregir les infraccions que es produeixin.
Passos d'eliminació
- Supressió de BST : elimina el node utilitzant regles BST estàndard.
- Fixa doble negre :
- Si s'elimina un node negre, es pot produir una condició de doble negre, que requereix correccions específiques.
Correcció de les infraccions durant la supressió
Quan s'elimina un node negre, gestionem el problema del doble negre en funció del color del germà i dels colors dels seus fills:
- Cas 1: el germà és vermell : Gira el pare i torna a pintar el germà i el pare.
- Cas 2: el germà és negre :
- Subcas 2.1: els fills dels germans són negres : Torna a pintar el germà i propaga el doble negre cap amunt.
- Subcas 2.2: Almenys un dels fills del germà és vermell :
- Si el fill llunyà del germà és vermell : Feu una rotació sobre el pare i el germà, i torneu a pintar adequadament.
- Si el fill proper del germà és vermell : Gireu el germà i el seu fill i, a continuació, manegeu-lo com a dalt.
4. Rotació
Les rotacions són operacions fonamentals per mantenir l'estructura equilibrada d'un arbre vermell-negre (RBT). Ajuden a preservar les propietats de l'arbre, assegurant que el camí més llarg des de l'arrel fins a qualsevol fulla no sigui més del doble de la longitud del camí més curt. Les rotacions són de dos tipus: rotacions a l'esquerra i rotacions a la dreta.
1. Rotació esquerra
Una rotació a l'esquerra al node 𝑥 x es mou 𝑥 x cap avall a l'esquerra i el seu fill dret 𝑦 i fins a prendre 𝑥 x el lloc.
Visualització de la rotació a l'esquerra Before Rotation: x y / a b After Left Rotation: y / x b / a>
Passos de rotació a l'esquerra:
- Conjunt i per ser el fill adequat x .
- Mou-te i subarbre esquerre a x el subarbre correcte.
- Actualitza el pare de x i i .
- Actualització x el pare per assenyalar i en lloc de x .
- Conjunt i li queda fill x .
- Actualització x el pare a i .
Pseudocodi de rotació a l'esquerra:
Rotació a l'esquerra // Utility function to perform left rotation void leftRotate(Node* x) { Node* y = x->dret; x->dreta = y->esquerra; if (y->esquerra != NIL) { y->esquerra->pare = x; } y->parent = x->parent; if (x->parent == nullptr) { arrel = y; } else if (x == x->pare->esquerra) { x->pare->esquerra = y; } else { x->parent->dret = y; } y->esquerra = x; x->parent = y; }>>> 2. Rotació dreta
Una rotació dreta al node 𝑥 x es mou 𝑥 x cap avall a la dreta i el seu fill esquerre 𝑦 i fins a prendre 𝑥 x el lloc.
Visualització de la rotació dreta: Passos de rotació dreta: - Conjunt i ser el fill esquerre de x .
- Mou-te i el subarbre correcte a x el subarbre esquerre.
- Actualitza el pare de x i i .
- Actualització x el pare per assenyalar i en lloc de x .
- Conjunt i el nen adequat x .
- Actualització x el pare a i .
Pseudocodi de rotació dreta:
C++ // Utility function to perform right rotation void rightRotate(Node* x) { Node* y = x->esquerra; x->esquerra = y->dreta; if (y->dreta != NIL) { y->dreta->pare = x; } y->parent = x->parent; if (x->parent == nullptr) { arrel = y; } else if (x == x->parent->dret) { x->pare->dret = y; } else { x->parent->esquerra = y; } y->dreta = x; x->parent = y; }>>>
Quan fer les rotacions?
Les rotacions als arbres vermell-negre es realitzen normalment durant les insercions i les supressions per mantenir les propietats de l'arbre. A continuació es mostren els escenaris per a les rotacions:
1. Arreglar les infraccions després de la inserció
Quan s'insereix un nou node, sempre està de color vermell. Això pot crear violacions de les propietats de l'arbre vermell-negre, concretament:
- L'arrel ha de ser negre .
- Vermell els nodes no poden tenir vermell nens.
Anàlisi de casos per arreglar insercions:
- Cas 1: Recolorir i propagar cap amunt
- Si el pare i l'oncle del nou node són tots dos vermell , torna a pintar el pare i l'oncle negre , i l'avi a vermell . A continuació, apliqueu recursivament la correcció a l'avi.
- Cas 2: Rotació i recolor
- Si l'oncle del nou node és negre i el nou node és el fill dret d'un fill esquerre (o viceversa), feu una rotació per moure el nou node cap amunt i alinear-lo.
- Si l'oncle del nou node és negre i el nou node és el fill esquerre d'un fill esquerre (o dret d'un dret), realitzeu una rotació i torneu a pintar el pare i l'avi per solucionar la violació.
2. Arreglar les infraccions després de la supressió
Després de la supressió, és possible que l'arbre hagi de reparar per restaurar les propietats:
- Quan s'elimina un node negre o se substitueix un node vermell per un node negre, pot sorgir una situació de doble negre.
Anàlisi de casos per solucionar les supressions:
- Cas 1: el germà és vermell
- Recoloreu el germà i el pare i feu una rotació.
- Cas 2: el germà és negre amb nens negres
- Recoloreu el germà al vermell i traslladeu el problema als pares.
- Cas 3: el germà és negre amb almenys un nen vermell
- Gira i torna a pintar per solucionar el problema del doble negre.
Implementació de l'arbre vermell-negre:
Aquí hi ha una implementació detallada d'un arbre vermell-negre que inclou funcions d'inserció, cerca i rotació:
C++dret; x->dreta = y->esquerra; if (y->esquerra != NIL) { y->esquerra->pare = x; } y->parent = x->parent; if (x->parent == nullptr) { arrel = y; } else if (x == x->pare->esquerra) { x->pare->esquerra = y; } else { x->parent->dret = y; } y->esquerra = x; x->parent = y; } // Funció d'utilitat per fer la rotació dreta void rightRotate(Node* x) { Node* y = x->esquerra; x->esquerra = y->dreta; if (y->dreta != NIL) { y->dreta->pare = x; } y->parent = x->parent; if (x->parent == nullptr) { arrel = y; } else if (x == x->pare->dret) { x->pare->dret = y; } else { x->parent->esquerra = y; } y->dreta = x; x->parent = y; } // Funció per corregir les propietats de l'arbre vermell-negre després de // inserció void fixInsert(Node* k) { while (k != arrel && k->parent->color == 'RED') { if (k->pare == k->pare->parent->esquerra) { Node* u = k->pare->pare->dreta; // oncle if (u->color == 'VERMELL') { k->parent->color = 'NEGRE'; u->color = 'NEGRE'; k->parent->parent->color = 'VERMELL'; k = k->pares->pares; } else { if (k == k->parent->dret) { k = k->parent; Girar a l'esquerra (k); } k->parent->color = 'NEGRE'; k->parent->parent->color = 'VERMELL'; rightRotate(k->parent->parent); } } else { Node* u = k->pare->pare->esquerra; // oncle if (u->color == 'VERMELL') { k->parent->color = 'NEGRE'; u->color = 'NEGRE'; k->parent->parent->color = 'VERMELL'; k = k->pares->pares; } else { if (k == k->parent->esquerra) { k = k->parent; Girar a la dreta (k); } k->parent->color = 'NEGRE'; k->parent->parent->color = 'VERMELL'; leftRotate(k->pare->pare); } } } arrel->color = 'NEGRE'; } // Funció d'ajuda per a la travessa en ordre void inorderHelper(Node* node) { if (node != NIL) { inorderHelper(node->esquerra); cout<< node->dades<< ' '; inorderHelper(node->dret); } } // Funció auxiliar de cerca Node* searchHelper (Node* node, int dades) { if (node == NIL || dades == node->dades) { retorn node; } si (dades< node->dades) { return searchHelper (node->esquerra, dades); } retorna l'Ajudant de cerca (node->dreta, dades); } public: // Constructor RedBlackTree () { NIL = nou Node (0); NIL->color = 'NEGRE'; NIL->esquerra = NIL->dreta = NIL; arrel = NIL; } // Insereix la funció void insert(in data) { Node* new_node = new Node (dades); nou_node->esquerra = NIL; nou_node->dreta = NIL; Node* pare = nullptr; Node* actual = arrel; // BST inserit mentre (actual != NIL) { pare = actual; if (nou_node->dades< current->dades) { actual = actual->esquerra; } else { actual = actual->dreta; } } nou_node->parent = pare; if (parent == nullptr) { arrel = nou_node; } else if (nou_node->dades< parent->dades) { pare->esquerra = nou_node; } else { pare->dreta = nou_node; } if (nou_node->parent == nullptr) { nou_node->color = 'BLACK'; tornar; } if (nou_node->parent->parent == nullptr) { retorn; } fixInsert(nou_node); } // Inorder traversal void inorder() { inorderHelper(arrel); } // Funció de cerca Node* search(int data) { return searchHelper(arrel, dades); }}; int main() { RedBlackTree rbt; // Inserint elements rbt.insert(10); rbt.insert(20); rbt.insert(30); rbt.insert(15); // Inordre travessa cout<< 'Inorder traversal:' << endl; rbt.inorder(); // Output: 10 15 20 30 // Search for a node cout << '
Search for 15: ' << (rbt.search(15) != rbt.search(0)) << endl; // Output: 1 (true) cout << 'Search for 25: ' << (rbt.search(25) != rbt.search(0)) << endl; // Output: 0 (false) return 0; }>
Avantatges dels arbres vermells i negres:
- Equilibrat: Els arbres vermell-negre s'autoequilibren, és a dir, mantenen automàticament un equilibri entre les altures dels subarbres esquerre i dret. Això assegura que les operacions de cerca, inserció i supressió triguen O(log n) temps en el pitjor dels casos.
- Cerca, inserció i supressió eficients: A causa de la seva estructura equilibrada, els arbres vermells-negres ofereixen operacions eficients. La cerca, la inserció i la supressió requereixen temps O(log n) en el pitjor dels casos.
- Fàcil d'implementar: Les regles per mantenir les propietats de l'arbre vermell-negre són relativament simples i senzilles d'implementar.
- Àmpliament utilitzat: Els arbres vermells i negres són una opció popular per implementar diverses estructures de dades, com ara mapes, conjunts i cues de prioritat.
Desavantatges dels arbres vermells i negres:
- Més complex que altres arbres equilibrats: En comparació amb arbres equilibrats més simples com els arbres AVL, els arbres vermells-negres tenen regles d'inserció i supressió més complexes.
- Càrrec constant: Mantenir les propietats de l'arbre vermell-negre afegeix una petita sobrecàrrega a cada operació d'inserció i supressió.
- No és òptim per a tots els casos d'ús: Tot i que és eficient per a la majoria de les operacions, els arbres vermells i negres poden no ser la millor opció per a aplicacions on es requereixen insercions i supressions freqüents, ja que la sobrecàrrega constant pot arribar a ser significativa.
Aplicacions dels arbres vermells i negres:
- Implementació de mapes i conjunts: Els arbres vermells i negres s'utilitzen sovint per implementar mapes i conjunts, on la cerca, la inserció i la supressió eficients són crucials.
- Cues de prioritat: Els arbres vermell-negre es poden utilitzar per implementar cues de prioritat, on els elements s'ordenen en funció de la seva prioritat.
- Sistemes de fitxers: Els arbres vermells i negres s'utilitzen en alguns sistemes de fitxers per gestionar estructures de fitxers i directoris.
- Bases de dades en memòria: Els arbres vermells i negres de vegades s'utilitzen a les bases de dades a la memòria per emmagatzemar i recuperar dades de manera eficient.
- Desenvolupament de gràfics i jocs: Els arbres vermells i negres es poden utilitzar en gràfics i jocs desenvolupament per a tasques com la detecció de col·lisions i la recerca de camins.
Preguntes freqüents (FAQ) sobre Red-Black Tree:
1. Què és un arbre vermell-negre?
Un arbre vermell-negre és un arbre de cerca binari d'autoequilibri que manté un equilibri entre les altures dels seus subarbres esquerre i dret. Això assegura que les operacions de cerca, inserció i supressió triguen O(log n) temps en el pitjor dels casos. Els arbres vermells-negres s'utilitzen àmpliament en diverses aplicacions on es requereixen estructures de dades eficients.
2. Com manté l'equilibri un arbre vermell-negre?
Els arbres vermell-negre mantenen el seu equilibri aplicant regles específiques sobre els colors dels nodes (VERMELL o NEGRE) i les relacions entre ells. Aquestes regles asseguren que l'arbre es mantingui equilibrat i que la diferència d'alçada entre els subarbres esquerre i dret sigui com a màxim d'1.
un objecte en java
3. Quins són els avantatges d'utilitzar un arbre vermell-negre?
- Equilibrat: Els arbres vermell-negre s'autoequilibren, garantint operacions eficients de cerca, inserció i supressió.
- Eficient: Ofereixen complexitat temporal O(log n) per a la majoria de les operacions.
- Fàcil d'implementar: Les regles per mantenir les propietats de l'arbre vermell-negre són relativament senzilles.
- Àmpliament utilitzat: Són una opció popular per implementar diverses estructures de dades i algorismes.
4. Quins són els desavantatges d'utilitzar un arbre vermell-negre?
- En comparació amb arbres equilibrats més simples com els arbres AVL, els arbres vermells-negres tenen regles d'inserció i supressió més complexes.
- Mantenir les propietats de l'arbre vermell-negre afegeix una petita sobrecàrrega a cada operació d'inserció i supressió.
- Per a aplicacions amb insercions i supressions freqüents, altres estructures d'arbre equilibrades poden ser més adequades.
5. Quines són algunes de les aplicacions habituals dels arbres vermells-negres?
- Implementació de mapes i conjunts
- Cues de prioritat
- Sistemes de fitxers
- Bases de dades en memòria
- Desenvolupament de gràfics i jocs (detecció de col·lisions, recerca de camins)
Articles relacionats:
- Definició i significat d'arbre vermell-negre a DSA
- Arbres de cerca binaris d'autoequilibri
- Arbre negre vermell vs Arbre AVL
- Quina diferència hi ha entre Heap i Red-Black Tree?
- Inserció en arbre vermell-negre
- Eliminació a l'arbre vermell-negre
- Arbres vermell-negres | Inserció de dalt a baix