Splay tree és una estructura de dades d'arbre de cerca binària que s'ajusta automàticament, la qual cosa significa que l'estructura de l'arbre s'ajusta dinàmicament en funció dels elements als quals s'accedeix o s'insereixen. En altres paraules, l'arbre es reorganitza automàticament de manera que els elements que s'hi accedeixen o s'insereixen amb freqüència s'acosten al node arrel.
- L'arbre splay va ser introduït per primera vegada per Daniel Dominic Sleator i Robert Endre Tarjan l'any 1985. Té una implementació senzilla i eficient que li permet realitzar operacions de cerca, inserció i supressió en O(log n) complexitat de temps amortitzat, on n és el nombre d'elements de l'arbre.
- La idea bàsica darrere dels arbres splay és portar l'element més recentment accedit o inserit a l'arrel de l'arbre realitzant una seqüència de rotacions de l'arbre, anomenada splaying. Splaying és un procés de reestructuració de l'arbre fent que l'element més recentment accedit o inserit sigui la nova arrel i apropant gradualment els nodes restants a l'arrel.
- Els arbres Splay són molt eficients a la pràctica a causa de la seva naturalesa autoajustable, que redueix el temps global d'accés als elements d'accés freqüent. Això els converteix en una bona opció per a aplicacions que requereixen estructures de dades ràpides i dinàmiques, com ara sistemes de memòria cau, compressió de dades i algorismes d'encaminament de xarxa.
- Tanmateix, el principal desavantatge dels arbres splay és que no garanteixen una estructura d'arbre equilibrada, la qual cosa pot provocar una degradació del rendiment en el pitjor dels escenaris. A més, els arbres splay no són adequats per a aplicacions que requereixen un rendiment garantit en el pitjor dels casos, com ara sistemes en temps real o sistemes crítics per a la seguretat.
En general, els arbres splay són una estructura de dades potent i versàtil que ofereix un accés ràpid i eficaç als elements d'accés freqüent o inserits. S'utilitzen àmpliament en diverses aplicacions i proporcionen un excel·lent compromís entre rendiment i simplicitat.
Un arbre splay és un arbre de cerca binari d'autoequilibri, dissenyat per a un accés eficient als elements de dades en funció dels seus valors clau.
- La característica clau d'un arbre splay és que cada vegada que s'accedeix a un element, es mou a l'arrel de l'arbre, creant una estructura més equilibrada per als accessos posteriors.
- Els arbres Splay es caracteritzen pel seu ús de rotacions, que són transformacions locals de l'arbre que canvien la seva forma però conserven l'ordre dels elements.
- Les rotacions s'utilitzen per portar l'element accedit a l'arrel de l'arbre, i també per reequilibrar l'arbre si es desequilibra després de múltiples accessos.
Operacions en un arbre de desplegament:
- Inserció: Per inserir un element nou a l'arbre, comenceu fent una inserció normal d'arbre de cerca binària. A continuació, apliqueu rotacions per portar l'element nou inserit a l'arrel de l'arbre.
- Supressió : Per eliminar un element de l'arbre, primer localitzeu-lo mitjançant una cerca binària en l'arbre. Aleshores, si l'element no té fills, elimineu-lo. Si té un fill, promou-lo a la seva posició a l'arbre. Si té dos fills, busqueu el successor de l'element (l'element més petit del seu subarbre dret), intercanvieu la seva clau amb l'element que voleu suprimir i suprimiu el successor.
- Cerca : Per cercar un element a l'arbre, comenceu fent una cerca binària en l'arbre. Si es troba l'element, apliqueu rotacions per portar-lo a l'arrel de l'arbre. Si no es troba, apliqueu rotacions a l'últim node visitat a la cerca, que es converteix en la nova arrel.
- Rotació : Les rotacions que s'utilitzen en un arbre de desplegament són una rotació Zig o Zig-Zig. Una rotació Zig s'utilitza per portar un node a l'arrel, mentre que una rotació Zig-Zig s'utilitza per equilibrar l'arbre després d'accedir múltiples als elements del mateix subarbre.
Aquí teniu una explicació pas a pas de les operacions de rotació:
- Rotació en zig : Si un node té un fill correcte, feu una rotació correcta per portar-lo a l'arrel. Si té un fill esquerre, feu una rotació a l'esquerra.
- Rotació Zig-Zig: Si un node té un nét que també és el fill dret o esquerre del seu fill, feu una doble rotació per equilibrar l'arbre. Per exemple, si el node té un fill dret i el fill dret té un fill esquerre, feu una rotació dreta-esquerra. Si el node té un fill esquerre i el fill esquerre té un fill dret, feu una rotació esquerra-dreta.
- Nota: Els detalls específics de la implementació, incloses les rotacions exactes utilitzades, poden variar segons la forma exacta de l'arbre de desplegament.
Rotacions a Splay Tree
- Rotació en zig
- Rotació Zag
- Zig – Zig Rotació
- Zag - Rotació Zag
- Rotació en zig-zag
- Zag: rotació en zig
1) Rotació en zig:
La rotació en zig en els arbres splay funciona d'una manera similar a la rotació única a la dreta en les rotacions d'arbre AVL. Aquesta rotació fa que els nodes es moguin una posició cap a la dreta des de la seva ubicació actual. Per exemple, considereu l'escenari següent:

Rotació en zig (rotació única)
2) Rotació Zag:
La rotació Zag en els arbres splay funciona de manera similar a la rotació a l'esquerra única en les rotacions d'arbre AVL. Durant aquesta rotació, els nodes es desplacen una posició cap a l'esquerra des de la seva ubicació actual. Per exemple, considereu la il·lustració següent:
decodificació javascript base64

Rotació Zag (rotació única a l'esquerra)
3) Rotació Zig-Zig:
La rotació en zig-zig als arbres splay és una rotació en zig doble. Aquesta rotació fa que els nodes canviïn de dues posicions cap a la dreta des de la seva ubicació actual. Mireu l'exemple següent per a una millor comprensió:

Rotació zig-zig (rotació doble dreta)
4) Rotació Zag-Zag:
En els arbres splay, la rotació Zag-Zag és una rotació doble zag. Aquesta rotació fa que els nodes es moguin dues posicions cap a l'esquerra des de la seva posició actual. Per exemple:

Rotació Zag-Zag (rotació doble a l'esquerra)
5) Rotació en zig-zag:
La rotació en zig-zag als arbres splay és una combinació d'una rotació en zig seguida d'una rotació en zag. Com a resultat d'aquesta rotació, els nodes es desplacen una posició cap a la dreta i després una posició cap a l'esquerra des de la seva ubicació actual. La il·lustració següent proporciona una representació visual d'aquest concepte:

Rotació en zig-zag
instal·lar maven
6) Rotació Zag-Zig:
La rotació Zag-Zig als arbres splay és una sèrie de rotacions en zag seguides d'una rotació en zig. Això fa que els nodes es moguin una posició cap a l'esquerra, seguit d'un canvi d'una posició cap a la dreta des de la seva ubicació actual. La il·lustració següent ofereix una representació visual d'aquest concepte:

Rotació Zag-Zig
A continuació es mostra el codi C++ per implementar rotacions a l'arbre Splay:
C++ #include using namespace std; struct Node { int key; Node *left, *right; }; Node* newNode(int key) { Node* node = new Node(); node->clau = clau; node->esquerra = node->dreta = nullptr; node de retorn; } Node* rightRotate(Node* x) { Node* y = x->esquerra; x->esquerra = y->dreta; y->dreta = x; retornar y; } Node* leftRotate(Node* x) { Node* y = x->right; x->dreta = y->esquerra; y->esquerra = x; retornar y; } Node* splay(Node* arrel, clau int) { if (arrel == nullptr || arrel->clau == clau) retornar arrel; if (arrel->clau> clau) { if (arrel->esquerra == nullptr) retornar arrel; if (arrel->esquerra->tecla> clau) { arrel->esquerra->esquerra = splay (arrel->esquerra->esquerra, clau); arrel = rightRotate (arrel); } else if (arrel->esquerra->clau< key) { root->esquerra->dreta = splay (arrel->esquerra->dreta, clau); if (arrel->esquerra->dreta != nullptr) arrel->esquerra = esquerraRotate (arrel->esquerra); } retorn (arrel->esquerra == nullptr) ? arrel: rightRotate (arrel); } else { if (arrel->dreta == nullptr) retorna arrel; if (arrel->dreta->clau> clau) { arrel->dreta->esquerra = splay (arrel->dreta->esquerra, clau); if (arrel->dreta->esquerra != nullptr) arrel->dreta = dretaRotar (arrel->dreta); } else if (arrel->dreta->clau< key) { root->dreta->dreta = splay(arrel->dreta->dreta, clau); arrel = leftRotate(arrel); } retorn (arrel->dreta == nullptr) ? arrel: leftRotate(arrel); } } Node* insert(Node* arrel, clau int) { if (arrel == nullptr) retorn nouNode(clau); arrel = splay (arrel, clau); if (arrel->clau == clau) retorna arrel; Node* node = nouNode(clau); if (arrel->clau> clau) { node->dreta = arrel; node->esquerra = arrel->esquerra; arrel->esquerra = nullptr; } else { node->esquerra = arrel; node->dreta = arrel->dreta; arrel->dreta = nullptr; } node de retorn; } void preOrder (Node* node) { if (node != nullptr) { cout<< node->clau<< ' '; preOrder(node->esquerra); preordre (node->dreta); } } int main() { Node* arrel = nullptr; arrel = inserir (arrel, 100); arrel = inserir (arrel, 50); arrel = inserir (arrel, 200); arrel = inserir (arrel, 40); arrel = inserir (arrel, 60); cout<< 'Preorder traversal of the modified Splay tree:' << endl; preOrder(root); return 0; }> Java // Java Program for the above approach class Node { public int key; public Node left, right; } class SplayTree { static Node newNode(int key) { Node node = new Node(); node.key = key; node.left = node.right = null; return node; } static Node rightRotate(Node x) { Node y = x.left; x.left = y.right; y.right = x; return y; } static Node leftRotate(Node x) { Node y = x.right; x.right = y.left; y.left = x; return y; } static Node splay(Node root, int key) { if (root == null || root.key == key) return root; if (root.key>clau) { if (root.left == null) retorna arrel; if (root.left.key> key) { root.left.left = splay (root.left.left, key); arrel = rightRotate (arrel); } else if (root.left.key< key) { root.left.right = splay(root.left.right, key); if (root.left.right != null) root.left = leftRotate(root.left); } return (root.left == null) ? root : rightRotate(root); } else { if (root.right == null) return root; if (root.right.key>clau) { root.right.left = splay (root.right.left, key); if (arrel.dreta.esquerra != nul) arrel.dreta = girar a la dreta (arrel.dreta); } else if (arrel.tecla.dreta< key) { root.right.right = splay(root.right.right, key); root = leftRotate(root); } return (root.right == null) ? root : leftRotate(root); } } static Node insert(Node root, int key) { if (root == null) return newNode(key); root = splay(root, key); if (root.key == key) return root; Node node = newNode(key); if (root.key>clau) { node.right = arrel; node.left = arrel.esquerra; arrel.esquerra = nul; } else { node.esquerra = arrel; node.right = arrel.dreta; arrel.dreta = nul; } node de retorn; } static void preOrder(Node node) { if (node != null) { System.out.println(); System.out.print(node.key + ' '); preordre (node.esquerra); preordre (node.dreta); } } public static void main(String[] args) { Arrel del node = nul; arrel = inserir (arrel, 100); arrel = inserir (arrel, 50); arrel = inserir (arrel, 200); arrel = inserir (arrel, 40); arrel = inserir (arrel, 60); System.out.println('Recorreu la comanda prèvia de l'arbre Splay modificat:'); preordre (arrel); } } // Aquest codi és aportat per princekumaras>>>Python 3 C# // C# program for the above approach using System; class Node { public int key; public Node left, right; } class SplayTree { static Node newNode(int key) { Node node = new Node(); node.key = key; node.left = node.right = null; return node; } static Node rightRotate(Node x) { Node y = x.left; x.left = y.right; y.right = x; return y; } static Node leftRotate(Node x) { Node y = x.right; x.right = y.left; y.left = x; return y; } static Node splay(Node root, int key) { if (root == null || root.key == key) return root; if (root.key>clau) { if (root.left == null) retorna arrel; if (root.left.key> key) { root.left.left = splay (root.left.left, key); arrel = rightRotate (arrel); } else if (root.left.key< key) { root.left.right = splay(root.left.right, key); if (root.left.right != null) root.left = leftRotate(root.left); } return (root.left == null) ? root : rightRotate(root); } else { if (root.right == null) return root; if (root.right.key>clau) { root.right.left = splay (root.right.left, key); if (arrel.dreta.esquerra != nul) arrel.dreta = girar a la dreta (arrel.dreta); } else if (arrel.tecla.dreta< key) { root.right.right = splay(root.right.right, key); root = leftRotate(root); } return (root.right == null) ? root : leftRotate(root); } } static Node insert(Node root, int key) { if (root == null) return newNode(key); root = splay(root, key); if (root.key == key) return root; Node node = newNode(key); if (root.key>clau) { node.right = arrel; node.left = arrel.esquerra; arrel.esquerra = nul; } else { node.esquerra = arrel; node.right = arrel.dreta; arrel.dreta = nul; } node de retorn; } static void preOrder(Node node) { if (node != null) { Console.Write(node.key + ' '); preordre (node.esquerra); preordre (node.dreta); } } public static void Principal(string[] args) { Arrel del node = nul; arrel = inserir (arrel, 100); arrel = inserir (arrel, 50); arrel = inserir (arrel, 200); arrel = inserir (arrel, 40); arrel = inserir (arrel, 60); Console.WriteLine('Recorreu la comanda prèvia de l'arbre Splay modificat:'); preordre (arrel); } } // Aquest codi és aportat pel príncep Kumar>>>Javascript>>
Sortida - Arbres desequilibrats: Els arbres Splay poden arribar a ser desequilibrats i ineficients si l'arbre es gira repetidament en la mateixa direcció.
- Ús de memòria: Els arbres Splay poden utilitzar molta memòria en comparació amb altres estructures de dades perquè cada node conté informació addicional.
- Complexitat: Els arbres Splay poden tenir una gran complexitat temporal per a operacions bàsiques com ara la inserció i la supressió, perquè els arbres s'han de reorganitzar després de cada operació.
- Despeses generals de reorganització: L'operació de desplegament requerida en cada operació pot consumir molt de temps i donar lloc a una sobrecàrrega elevada.
- Casos d'ús limitat : els arbres Splay no són adequats per a totes les estructures de dades i tenen casos d'ús limitats perquè no gestionen les claus duplicades de manera eficient.
Aplicacions de l'arbre splay:
- Emmagatzematge a la memòria cau : els arbres Splay es poden utilitzar per implementar la gestió de la memòria cau, on els elements als quals s'accedeix amb més freqüència es mouen a la part superior de l'arbre per a un accés més ràpid.
- Indexació de bases de dades : els arbres Splay es poden utilitzar per indexar bases de dades per a una cerca i recuperació de dades més ràpida.
- Sistemes de fitxers : els arbres Splay es poden utilitzar per emmagatzemar metadades del sistema de fitxers, com ara la taula d'assignació, l'estructura de directoris i els atributs del fitxer.
- Compressió de dades: Els arbres Splay es poden utilitzar per comprimir dades identificant i codificant patrons repetitius.
- Tractament de text : els arbres Splay es poden utilitzar en aplicacions de processament de text, com ara els correctors ortogràfics, on les paraules s'emmagatzemen en un arbre Splay per a una cerca i recuperació ràpida.
- Algorismes gràfics: Els arbres Splay es poden utilitzar per implementar algorismes de gràfics, com ara trobar el camí més curt en un gràfic ponderat.
- Jocs en línia: Els arbres Splay es poden utilitzar en jocs en línia per emmagatzemar i gestionar puntuacions altes, taules de classificació i estadístiques de jugadors.
Per descomptat, aquí hi ha alguns avantatges i desavantatges dels arbres splay, així com alguns llibres recomanats per aprendre més sobre el tema:
Avantatges de Splay Trees:
Els arbres Splay han amortitzat la complexitat del temps d'O(log n) per a moltes operacions, fent-les més ràpides que moltes altres estructures de dades d'arbre equilibrades en alguns casos.
Els arbres Splay s'ajusten automàticament, és a dir, s'equilibren automàticament a mesura que s'insereixen i s'eliminen els elements. Això pot ajudar a evitar la degradació del rendiment que es pot produir quan un arbre es desequilibra.
herència en java
Desavantatges de Splay Trees:
Els arbres Splay poden tenir la pitjor complexitat temporal d'O (n) per a algunes operacions, cosa que els fa menys predictibles que altres estructures de dades d'arbre equilibrat com els arbres AVL o els arbres vermell-negre.
És possible que els arbres Splay no siguin adequats per a determinades aplicacions on es requereix un rendiment previsible.
Llibres recomanats sobre Splay Trees:
Estructures de dades i anàlisi d'algoritmes en Java per Mark Allen Weiss
Introducció als algoritmes de Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest i Clifford Stein
Estructures de dades i algoritmes en C++ de Michael T. Goodrich i Roberto Tamassia
Conclusió:
En conclusió, els Splay Trees són una estructura de dades d'arbre de cerca binària d'autoequilibri dinàmic que proporciona una manera eficient de cercar, inserir i suprimir elements. Es diferencien dels arbres de cerca binaris equilibrats tradicionals com els arbres AVL i vermell-negre, ja que reorganitzen l'arbre després de cada operació per portar el node accedit recentment a l'arrel. Això ajuda a reduir l'alçada de l'arbre i es tradueix en operacions més ràpides. Els Splay Trees són molt flexibles i es poden adaptar a diversos casos d'ús. Tot i que poden tenir una sobrecàrrega més elevada pel que fa a les rotacions, la seva senzillesa i versatilitat els converteixen en eines útils per resoldre un ampli ventall de problemes.