Estrategias de Recorrido en Árboles Binarios con Python: Recursivo y por Niveles

Fundamentos de los Algoritmos de Visita

El procesamiento de nodos en un árbol binario depende del orden en que se accede a la raíz relativa a sus hijos. Existen patrones estandarizados:

  • Paso Primero (Preorden): Se evalúa el nodo padre antes de sus descendientes (Raíz → Izquierda → Derecha).
  • Paso Medio (Inorden): Se recorre primero el subárbol izquierdo, luego se centra en el nodo actual y finalmenet se aborda la rama derecha (Izquierda → Raíz → Derecha).
  • Paso Último (Posorden): Los descendientes se procesan completamente antes de visitar la raíz (Izquierda → Derecha → Raíz).

Definición de Estructura y Clases Base

A continuación, se presenta una implementación modular donde se define el nodo individual y una clase contenedora para gestionar las operaciones. Se han utilizado nombres de variables más descriptivos y se ha implementado la lógica de retorno en lugar de solo imprimir.

class NodoArbol: def init(self, dato=None): self.valor = dato self.izquierdo = None self.derecho = None

class ArbolBinario: def init(self, raiz=NodoArbol()): self.raiz = raiz

def vacio(self) -> bool:
    return self.raiz is None

def preOrden(self, n):
    """Recorrido Preorden: Imprime valor, luego recursivamente izquierda y derecha."""
    if not n:
        return []
    resultado = [n.valor]
    resultado.extend(self.preOrden(n.izquierdo))
    resultado.extend(self.preOrden(n.derecho))
    return resultado

def inOrden(self, n):
    """Recorrido Inorden: Recursión izquierda, valor, recursión derecha."""
    if not n:
        return []
    return self.inOrden(n.izquierdo) + [n.valor] + self.inOrden(n.derecho)

def posOrden(self, n):
    """Recorrido Posorden: Recursión izquierda, derecha, luego valor."""
    if not n:
        return []
    return self.posOrden(n.izquierdo) + self.posOrden(n.derecho) + [n.valor]

</div>### Solución Iterativa para Nivel por Nivel

Para obtener el recorrido nivel por nivel (BFS), utilizamos una cola. El proceso consiste en extraer un nodo, registrar su valor y añadir sus hijos inmediatos al final de la cola. Para agrupar por niveles, controlamos la cantidad de elementos presentes en cada iteración del ciclo principal.

<div class="code-block">```
def nivelPorNivel(n):
    if not n:
        return []
    
    resultado_final = []
    cola = deque([n])
    
    while cola:
        tamanio_nivel = len(cola)
        grupo_actual = []
        
        for _ in range(tamanio_nivel):
            nodo = cola.popleft()
            grupo_actual.append(nodo.valor)
            
            if nodo.izquierdo:
                cola.append(nodo.izquierdo)
            if nodo.derecho:
                cola.append(nodo.derecho)
                
        resultado_final.append(grupo_actual)
    return resultado_final

La versión iterativa utiliza una pila (stack) explícita para simular la llamada recursiva. Primero se desciende hacia la izquierda almacenando los nodos en la pila hasta encontrar un null, luego se extrae para procesar y se dirige hacia la rama derecha.

while pilapila or nodo:
    while nodo:
        pilapila.append(nodo)
        nodo = nodo.izquierdo
    
    nodo = pilapila.pop()
    resultado.append(nodo.valor)
    nodo = nodo.derecho
return resultado

</div>### Cálculo de Profundidad y Transformación de Estructura

Ciertas proipedades del árbol requieren calcular métricas o modificar la topología. La profundidad máxima es la longitud del camino más largo desde la raíz. La inversión de árboles implica intercambiar sistemáticamente los hijos de cada nodo visitado.

<div class="code-block">```
def calcularProfundidadMaxima(n):
    if not n:
        return 0
    profundidad_izquierda = calcularProfundidadMaxima(n.izquierdo)
    profundidad_derecha = calcularProfundidadMaxima(n.derecho) # Corrección: usar hijo derecho
    return max(profundidad_izquierda, profundidad_derecha) + 1

def invertirArbol(n):
    if not n:
        return None
    
    # Intercambio recursivo de hijos
    temporal = self.invertirArbol(n.izquierdo)
    n.izquierdo = self.invertirArbol(n.derecho)
    n.derecho = temporal
    return n

Etiquetas: Python data-structures binary-tree traversal recursion

Publicado el 10-28 05:25