1#include <iostream>
2#include <algorithm>
3using namespace std;
4
5class Node { // Um nó guarda seu valor e ponteiros para seus dois filhos
6private: // Atributos privados: só os métodos acessam
7 int value;
8 Node* left;
9 Node* right;
10public:
11 Node(int v) : value(v), left(nullptr), right(nullptr) {}
12 int getValue() const { return value; }
13 Node* getLeft() const { return left; }
14 Node* getRight() const { return right; }
15 void setValue(int v) { value = v; }
16 void setLeft(Node* n) { left = n; }
17 void setRight(Node* n) { right = n; }
18};
19
20int height(Node* n) { // Altura: uma folha vale 1 e uma posição vazia (nullptr) vale 0
21 if (n == nullptr) return 0;
22 return 1 + max(height(n->getLeft()), height(n->getRight()));
23}
24
25int balanceFactor(Node* n) { // Fator de balanceamento: altura esquerda menos altura direita
26 return height(n->getLeft()) - height(n->getRight());
27}
28
29Node* rotateRight(Node* y) { // Rotação simples à direita: o filho esquerdo x sobe e y desce
30 Node* x = y->getLeft();
31 y->setLeft(x->getRight());
32 x->setRight(y);
33 return x;
34}
35
36Node* rotateLeft(Node* x) { // Rotação simples à esquerda: o filho direito y sobe e x desce
37 Node* y = x->getRight();
38 x->setRight(y->getLeft());
39 y->setLeft(x);
40 return y;
41}
42
43Node* rebalance(Node* n) { // Devolve a raiz da subárvore, balanceada
44 int bf = balanceFactor(n); // Calcula-se o fator de balanceamento do nó
45 if (bf > 1) { // Pesada à esquerda. Se o filho esquerdo não é pesado à direita, é o caso LL
46 if (balanceFactor(n->getLeft()) < 0) // O filho esquerdo é pesado à direita: caso LR, girar à esquerda primeiro
47 n->setLeft(rotateLeft(n->getLeft())); // Primeira rotação do caso LR
48 return rotateRight(n); // Rotação à direita: resolve LL e a segunda metade de LR
49 }
50 if (bf < -1) { // Pesada à direita. Se o filho direito não é pesado à esquerda, é o caso RR
51 if (balanceFactor(n->getRight()) > 0) // O filho direito é pesado à esquerda: caso RL, girar à direita primeiro
52 n->setRight(rotateRight(n->getRight())); // Primeira rotação do caso RL
53 return rotateLeft(n); // Rotação à esquerda: resolve RR e a segunda metade de RL
54 }
55 return n; // O fator está entre -1 e 1: não é preciso rotacionar
56}
57
58Node* insert(Node* root, int v) { // Insere v na árvore AVL e devolve a raiz
59 if (root == nullptr) // Posição vazia: o novo nó fica aqui
60 return new Node(v); // Cria o novo nó
61 if (v < root->getValue()) // Valores menores vão para a esquerda e maiores para a direita
62 root->setLeft(insert(root->getLeft(), v)); // Desce pela subárvore esquerda
63 else
64 root->setRight(insert(root->getRight(), v)); // Desce pela subárvore direita
65 return rebalance(root); // Na volta de cada chamada, verifica-se o balanceamento do nó
66}
67
68int main() {
69 Node* root = buildTree(); // A árvore exibida, já construída
70 root = insert(root, v); // Primeira chamada, a partir de main
71 return 0; // Fim da operação
72}