Last active
October 9, 2024 23:39
-
-
Save je4npw/c8f4ddb863fb5feb604d793606852496 to your computer and use it in GitHub Desktop.
Algoritmo em C++ para relatório de aula prática ALGORITMOS E ESTRUTURA DE DADOS AVANÇADO Anhanguera
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Para compilar: | |
// g++ -o avl avl.cpp | |
// Para executar: | |
// chmod +x avl | |
// ./relatorio1 | |
// retorna a saída das movimentações em nodes após os insert e remove na árvore avl | |
#include <iostream> | |
#include <algorithm> | |
using namespace std; | |
struct Node { | |
int key; | |
Node* left; | |
Node* right; | |
int height; | |
}; | |
// Função para obter a altura de um nó | |
int height(Node* N) { | |
return (N == nullptr) ? 0 : N->height; | |
} | |
// Função para obter o fator de balanceamento de um nó | |
int getBalance(Node* N) { | |
return (N == nullptr) ? 0 : height(N->left) - height(N->right); | |
} | |
// Função para criar um novo nó | |
Node* newNode(int key) { | |
Node* node = new Node(); | |
node->key = key; | |
node->left = nullptr; | |
node->right = nullptr; | |
node->height = 1; | |
return node; | |
} | |
// Função para desenhar a árvore AVL em ordem (in-order) | |
void printTree(Node* root, string indent = "", bool isLeft = true) { | |
if (root != nullptr) { | |
cout << indent; | |
if (isLeft) { | |
cout << "L----"; | |
indent += " "; | |
} else { | |
cout << "R----"; | |
indent += "| "; | |
} | |
cout << root->key << "(h=" << root->height << ")" << endl; | |
printTree(root->left, indent, true); | |
printTree(root->right, indent, false); | |
} | |
} | |
// Rotação simples à direita | |
Node* rightRotate(Node* y) { | |
cout << "Realizando rotação simples à direita no nó " << y->key << " pois a subárvore esquerda está desbalanceada." << endl; | |
Node* x = y->left; | |
Node* T2 = x->right; | |
// Realiza a rotação | |
x->right = y; | |
y->left = T2; | |
// Atualiza as alturas | |
y->height = max(height(y->left), height(y->right)) + 1; | |
x->height = max(height(x->left), height(x->right)) + 1; | |
return x; | |
} | |
// Rotação simples à esquerda | |
Node* leftRotate(Node* x) { | |
cout << "Realizando rotação simples à esquerda no nó " << x->key << " pois a subárvore direita está desbalanceada." << endl; | |
Node* y = x->right; | |
Node* T2 = y->left; | |
// Realiza a rotação | |
y->left = x; | |
x->right = T2; | |
// Atualiza as alturas | |
x->height = max(height(x->left), height(x->right)) + 1; | |
y->height = max(height(y->left), height(y->right)) + 1; | |
return y; | |
} | |
// Função para inserir um nó em uma árvore AVL | |
Node* insert(Node* node, int key) { | |
// Passo 1: Inserção normal em uma árvore binária de busca | |
if (node == nullptr) { | |
cout << "Inserindo " << key << " na árvore." << endl; | |
return newNode(key); | |
} | |
if (key < node->key) | |
node->left = insert(node->left, key); | |
else if (key > node->key) | |
node->right = insert(node->right, key); | |
else | |
return node; // Chaves duplicadas não são permitidas | |
// Passo 2: Atualiza a altura deste nó ancestral | |
node->height = 1 + max(height(node->left), height(node->right)); | |
// Passo 3: Verifica o fator de balanceamento deste nó | |
int balance = getBalance(node); | |
// Caso 1: Desbalanceado para a esquerda | |
if (balance > 1 && key < node->left->key) { | |
return rightRotate(node); | |
} | |
// Caso 2: Desbalanceado para a direita | |
if (balance < -1 && key > node->right->key) { | |
return leftRotate(node); | |
} | |
// Caso 3: Rotação dupla (esquerda-direita) | |
if (balance > 1 && key > node->left->key) { | |
cout << "Realizando rotação dupla (esquerda-direita) no nó " << node->key << " pois a inserção ocorreu na subárvore esquerda direita." << endl; | |
node->left = leftRotate(node->left); | |
return rightRotate(node); | |
} | |
// Caso 4: Rotação dupla (direita-esquerda) | |
if (balance < -1 && key < node->right->key) { | |
cout << "Realizando rotação dupla (direita-esquerda) no nó " << node->key << " pois a inserção ocorreu na subárvore direita esquerda." << endl; | |
node->right = rightRotate(node->right); | |
return leftRotate(node); | |
} | |
return node; | |
} | |
// Função para encontrar o nó com menor valor (usado na remoção) | |
Node* minValueNode(Node* node) { | |
Node* current = node; | |
while (current->left != nullptr) | |
current = current->left; | |
return current; | |
} | |
// Função para remover um nó da árvore AVL | |
Node* deleteNode(Node* root, int key) { | |
// Passo 1: Remoção normal em uma árvore binária de busca | |
if (root == nullptr) | |
return root; | |
if (key < root->key) | |
root->left = deleteNode(root->left, key); | |
else if (key > root->key) | |
root->right = deleteNode(root->right, key); | |
else { | |
// Nó com um ou nenhum filho | |
if ((root->left == nullptr) || (root->right == nullptr)) { | |
Node* temp = root->left ? root->left : root->right; | |
if (temp == nullptr) { | |
temp = root; | |
root = nullptr; | |
} else | |
*root = *temp; | |
delete temp; | |
} else { | |
Node* temp = minValueNode(root->right); | |
root->key = temp->key; | |
root->right = deleteNode(root->right, temp->key); | |
} | |
} | |
if (root == nullptr) | |
return root; | |
// Passo 2: Atualiza a altura do nó atual | |
root->height = 1 + max(height(root->left), height(root->right)); | |
// Passo 3: Verifica o fator de balanceamento | |
int balance = getBalance(root); | |
// Caso 1: Desbalanceado para a esquerda | |
if (balance > 1 && getBalance(root->left) >= 0) { | |
cout << "Realizando rotação simples à direita no nó " << root->key << " após a remoção." << endl; | |
return rightRotate(root); | |
} | |
// Caso 2: Rotação dupla (esquerda-direita) | |
if (balance > 1 && getBalance(root->left) < 0) { | |
cout << "Realizando rotação dupla (esquerda-direita) no nó " << root->key << " após a remoção." << endl; | |
root->left = leftRotate(root->left); | |
return rightRotate(root); | |
} | |
// Caso 3: Desbalanceado para a direita | |
if (balance < -1 && getBalance(root->right) <= 0) { | |
cout << "Realizando rotação simples à esquerda no nó " << root->key << " após a remoção." << endl; | |
return leftRotate(root); | |
} | |
// Caso 4: Rotação dupla (direita-esquerda) | |
if (balance < -1 && getBalance(root->right) > 0) { | |
cout << "Realizando rotação dupla (direita-esquerda) no nó " << root->key << " após a remoção." << endl; | |
root->right = rightRotate(root->right); | |
return leftRotate(root); | |
} | |
return root; | |
} | |
int main() { | |
Node* root = nullptr; | |
// Inserção de elementos | |
int elements[] = {20, 4, 26, 3, 9, 15, 30, 2, 7}; | |
for (int i = 0; i < 9; i++) { | |
root = insert(root, elements[i]); | |
cout << "Árvore após inserção de " << elements[i] << ":" << endl; | |
printTree(root); | |
cout << "--------------------------" << endl; | |
} | |
// Remoção de elementos | |
int toRemove[] = {26, 4, 9}; | |
for (int i = 0; i < 3; i++) { | |
root = deleteNode(root, toRemove[i]); | |
cout << "Árvore após remoção de " << toRemove[i] << ":" << endl; | |
printTree(root); | |
cout << "--------------------------" << endl; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Para compilar:
g++ -o avl avl.cpp
Para executar:
Retorna a saída das movimentações em nodes após os insert e remove na árvore avl