Invertir un Árbol Binario: Especificación y Implementación

En una publicación de Twitter, Max Howell mencionó: "Google: el 90% de nuestros ingenieros usan el software que desarrollaste (Homebrew), pero no puedes invertir un árbol binario en una pizarra, así que no eres apto." Ahora es tu oportunidad de demostrar que sí puedes lograrlo.

Especificación de Entrada:

Cada archivo de entrada contiene un caso de prueba. Para cada caso, la primera línea proporciona un entero positivo N (≤10) que indica el número total de nodos en el árbol, numerados del 0 al N-1. Luego siguen N líneas, cada una correspondiente a un nodo del 0 al N-1, que especifica los índices de los hijos izquierdo y derecho del nodo. Si un hijo no existe, se coloca un guion (-) en esa posición. Los índices de los hijos están separados por un espacio.

Especificación de Salida:

Para cada caso de prueba, imprime en la primera línea el recorrido por niveles, y en la segunda línea el recorrido en orden del árbol invertido. Debe haber exactamente un espacio entre números adyacentes, sin espacios adicionales al final de la línea.

Ejemplo de Entrada:

8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6

Ejemplo de Salida:

3 7 2 6 4 0 5 1
6 5 7 4 3 2 0 1

A continuación, se presenta una implementación en C++ que resuelve el problema. El código construye el árbol a partir de la entrada, lo invierte intercambiando los hijos izquierdo y derecho de cada nodo, y luego genera los recorridos requeridos. Se han modificado los nombres de las variables y la estructura para reducir la similitud con el origianl.

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

struct NodoArbol {
    int izquierdo = -1;
    int derecho = -1;
};

vector<int> recorridoEnOrden;
vector<int> recorridoPorNivel;

void construirEnOrden(int raiz, const vector<NodoArbol>& arbol) {
    if (raiz == -1) return;
    construirEnOrden(arbol[raiz].izquierdo, arbol);
    recorridoEnOrden.push_back(raiz);
    construirEnOrden(arbol[raiz].derecho, arbol);
}

void construirPorNivel(int raiz, const vector<NodoArbol>& arbol) {
    queue<int> cola;
    cola.push(raiz);
    while (!cola.empty()) {
        int nodoActual = cola.front();
        cola.pop();
        recorridoPorNivel.push_back(nodoActual);
        if (arbol[nodoActual].izquierdo != -1) cola.push(arbol[nodoActual].izquierdo);
        if (arbol[nodoActual].derecho != -1) cola.push(arbol[nodoActual].derecho);
    }
}

void invertirArbol(int raiz, vector<NodoArbol>& arbol) {
    if (raiz == -1) return;
    swap(arbol[raiz].izquierdo, arbol[raiz].derecho);
    invertirArbol(arbol[raiz].izquierdo, arbol);
    invertirArbol(arbol[raiz].derecho, arbol);
}

int main() {
    int cantidadNodos;
    cin >> cantidadNodos;

    vector<NodoArbol> arbol(cantidadNodos);

    for (int i = 0; i < cantidadNodos; ++i) {
        char hijoIzq, hijoDer;
        cin >> hijoIzq >> hijoDer;
        if (hijoIzq != '-') arbol[i].izquierdo = hijoIzq - '0';
        if (hijoDer != '-') arbol[i].derecho = hijoDer - '0';
    }

    // Encontrar la raíz (nodo sin padre)
    vector<bool> tienePadre(cantidadNodos, false);
    for (int i = 0; i < cantidadNodos; ++i) {
        if (arbol[i].izquierdo != -1) tienePadre[arbol[i].izquierdo] = true;
        if (arbol[i].derecho != -1) tienePadre[arbol[i].derecho] = true;
    }
    int raiz = -1;
    for (int i = 0; i < cantidadNodos; ++i) {
        if (!tienePadre[i]) {
            raiz = i;
            break;
        }
    }

    // Invertir el árbol
    invertirArbol(raiz, arbol);

    // Realizar recorridos
    recorridoEnOrden.clear();
    recorridoPorNivel.clear();
    construirEnOrden(raiz, arbol);
    construirPorNivel(raiz, arbol);

    // Imprimir recorrido por niveles
    for (size_t i = 0; i < recorridoPorNivel.size(); ++i) {
        if (i > 0) cout << " ";
        cout << recorridoPorNivel[i];
    }
    cout << endl;

    // Imprimir recorrido en orden
    for (size_t i = 0; i < recorridoEnOrden.size(); ++i) {
        if (i > 0) cout << " ";
        cout << recorridoEnOrden[i];
    }
    cout << endl;

    return 0;
}

Etiquetas: árbol binario inversión de árbol recorrido en orden C++ estructuras de datos

Publicado el 6-27 01:34