#include <Arduino.h>
#define PIN_R 18
#define PIN_G 19
#define PIN_B 21
enum Color { ROJO, NEGRO };
struct Nodo {
int dato;
Color color;
Nodo *izq, *der, *padre;
Nodo(int val, Color c = ROJO) : dato(val), color(c), izq(nullptr), der(nullptr), padre(nullptr) {}
};
class ArbolRN {
private:
Nodo* raiz = nullptr;
// ===== LED RGB CONTROL =====
void setColor(int r, int g, int b) {
digitalWrite(PIN_R, r ? HIGH : LOW);
digitalWrite(PIN_G, g ? HIGH : LOW);
digitalWrite(PIN_B, b ? HIGH : LOW);
}
public:
// ← ¡Importante! apagar() ahora es pública o la llamamos con un helper
void apagar() {
setColor(0, 0, 0);
}
void mostrarColorNodo(Color c, int dur = 500) {
if (c == ROJO) setColor(1, 0, 0); // Rojo
else setColor(0, 1, 0); // Verde
delay(dur);
apagar();
}
void flashRotacion(bool izquierda, int dur = 300) {
if (izquierda) setColor(0, 0, 1); // Azul
else setColor(1, 1, 0); // Amarillo
delay(dur);
apagar();
}
// ===== ROTACIONES CON EFECTOS =====
void rotarIzquierda(Nodo* x) {
flashRotacion(true);
Nodo* y = x->der;
x->der = y->izq;
if (y->izq) y->izq->padre = x;
y->padre = x->padre;
if (!x->padre) raiz = y;
else if (x == x->padre->izq) x->padre->izq = y;
else x->padre->der = y;
y->izq = x;
x->padre = y;
}
void rotarDerecha(Nodo* y) {
flashRotacion(false);
Nodo* x = y->izq;
y->izq = x->der;
if (x->der) x->der->padre = y;
x->padre = y->padre;
if (!y->padre) raiz = x;
else if (y == y->padre->der) y->padre->der = x;
else y->padre->izq = x;
x->der = y;
y->padre = x;
}
void arreglarInsercion(Nodo* k) {
while (k->padre && k->padre->color == ROJO) {
if (k->padre == k->padre->padre->izq) {
Nodo* tio = k->padre->padre->der;
if (tio && tio->color == ROJO) {
k->padre->color = NEGRO;
tio->color = NEGRO;
k->padre->padre->color = ROJO;
mostrarColorNodo(NEGRO, 200);
mostrarColorNodo(NEGRO, 200);
mostrarColorNodo(ROJO, 200);
k = k->padre->padre;
} else {
if (k == k->padre->der) {
k = k->padre;
rotarIzquierda(k);
}
k->padre->color = NEGRO;
k->padre->padre->color = ROJO;
mostrarColorNodo(NEGRO, 300);
mostrarColorNodo(ROJO, 300);
rotarDerecha(k->padre->padre);
}
} else {
Nodo* tio = k->padre->padre->izq;
if (tio && tio->color == ROJO) {
k->padre->color = NEGRO;
tio->color = NEGRO;
k->padre->padre->color = ROJO;
mostrarColorNodo(NEGRO, 200);
mostrarColorNodo(NEGRO, 200);
mostrarColorNodo(ROJO, 200);
k = k->padre->padre;
} else {
if (k == k->padre->izq) {
k = k->padre;
rotarDerecha(k);
}
k->padre->color = NEGRO;
k->padre->padre->color = ROJO;
mostrarColorNodo(NEGRO, 300);
mostrarColorNodo(ROJO, 300);
rotarIzquierda(k->padre->padre);
}
}
}
raiz->color = NEGRO;
}
public:
void insertar(int val, Color colorDeseado = ROJO) {
if (colorDeseado == NEGRO) {
Serial.println("Advertencia: No se permite nodo negro directo -> se inserta como ROJO");
}
mostrarColorNodo(ROJO, 600);
Nodo* nuevo = new Nodo(val, ROJO);
Nodo* padre = nullptr;
Nodo* actual = raiz;
while (actual) {
padre = actual;
actual = (nuevo->dato < actual->dato) ? actual->izq : actual->der;
}
nuevo->padre = padre;
if (!padre) raiz = nuevo;
else if (nuevo->dato < padre->dato) padre->izq = nuevo;
else padre->der = nuevo;
if (!padre) { raiz->color = NEGRO; return; }
arreglarInsercion(nuevo);
}
void imprimir() {
imprimirRec(raiz, 0);
Serial.println("---");
}
void imprimirRec(Nodo* n, int nivel) {
if (!n) return;
imprimirRec(n->der, nivel + 1);
for (int i = 0; i < nivel; i++) Serial.print(" ");
Serial.print(n->dato);
Serial.println(n->color == ROJO ? " (R)" : " (N)");
imprimirRec(n->izq, nivel + 1);
}
void borrarTodo() {
borrarRec(raiz);
raiz = nullptr;
}
void borrarRec(Nodo* n) {
if (n) {
borrarRec(n->izq);
borrarRec(n->der);
delete n;
}
}
};
ArbolRN arbol;
void setup() {
Serial.begin(115200);
delay(2000); // ← Delay más largo para inicializar bien el Serial en Wokwi
Serial.println("=== INICIANDO ARBOL ROJO-NEGRO + LED RGB ==="); // Primer print fuerte
Serial.println("¡Monitor Serial listo!"); // Segundo print para forzar apertura
Serial.println("1 = Insertar | 2 = Borrar arbol | 3 = Salir");
Serial.println("Escribe '1' para probar...");
pinMode(PIN_R, OUTPUT);
pinMode(PIN_G, OUTPUT);
pinMode(PIN_B, OUTPUT);
arbol.apagar();
}
void loop() {
if (Serial.available()) {
int opcion = Serial.parseInt(); // ← aquí estaba el error (if])
if (opcion == 1) {
Serial.print("Valor a insertar: ");
while (!Serial.available()) delay(10);
int valor = Serial.parseInt();
Serial.print("Color deseado (0=Rojo, 1=Negro): ");
while (!Serial.available()) delay(10);
int colorInt = Serial.parseInt();
Color colorDeseado = (colorInt == 1) ? NEGRO : ROJO;
arbol.insertar(valor, colorDeseado);
Serial.println("Arbol actual:");
arbol.imprimir();
}
else if (opcion == 2) {
arbol.borrarTodo();
Serial.println("Arbol eliminado!");
}
else if (opcion == 3) {
Serial.println("Chao!");
while(true) delay(1000);
}
}
}