Arboles

En informรกtica, un รกrbol es una estructura de datos jerรกrquica compuesta por nodos interconectados, donde cada nodo tiene un nodo padre (excepto la raรญz) y cero o mรกs nodos hijos. Estรก diseรฑado para organizar datos eficientemente, facilitando la bรบsqueda y manipulaciรณn de informaciรณn. Los รกrboles son fundamentales en la representaciรณn y estructuraciรณn de datos en algoritmos y aplicaciones informรกticas.

Conceptos bรกsicos

Aquรญ, exploraremos los conceptos bรกsicos de los รกrboles, sus elementos fundamentales y cรณmo se estructuran en la programaciรณn:

  • El predecesor de cualquier elemento se denomina padre del elemento

  • El nodo que no tiene padre y predecesor de todos los elementos de denomina raiz

  • Cada nodo puede tener 0 o mas hijos

  • Todo hijo es un subarbol

  • Los nodos sin hijos se denominan hojas

  • Anchura (fan-out): Maximo numero de hijos para un nodo cualquiera de un arbol

    • Arbol-general: tiene un fan-out acotado

    • Arboles binarios: Tiene un fan-out maximo de 2, es decir puede tener como maximo 2 hijos por cada nodo

  • Altura: Distancia maxima desde la raiz a cualquiera de las hojas

  • Nivel: Conjunto de nodos de un arbol que tienen la misma altura

Tipos de recorrido

Recorrido en Anchura (Breadth-First Traversal):

El recorrido en anchura, tambiรฉn conocido como BFS, explora el รกrbol nivel por nivel. Comienza visitando la raรญz y luego se mueve a sus nodos hijos antes de avanzar al siguiente nivel. Para implementarlo, utilizamos una cola para mantener un seguimiento del orden de visita. Este recorrido es eficaz para encontrar el camino mรกs corto en un grafo no ponderado y garantiza que los nodos se visiten en el orden en que aparecen en cada nivel.

BFS(raiz):
    cola = nueva Cola()
    cola.encolar(raiz)

    mientras cola no estรฉ vacรญa:
        nodo = cola.desencolar()
        imprimir nodo.valor

        si nodo.izquierdo no es nulo:
            cola.encolar(nodo.izquierdo)
        si nodo.derecho no es nulo:
            cola.encolar(nodo.derecho)

Recorrido en Profundidad - Preorden (Preorder Traversal):

En el recorrido en profundidad preorden, primero se visita el nodo actual, luego se realiza el mismo proceso en el subรกrbol izquierdo y, finalmente, en el subรกrbol derecho. Es รบtil para explorar la estructura del รกrbol antes de profundizar en niveles inferiores. Puede ser utilizado para crear una copia del รกrbol, imprimir una expresiรณn aritmรฉtica en notaciรณn prefija o realizar cualquier acciรณn que necesite procesar el nodo antes de sus hijos.

Preorden(raiz):
    si raiz no es nulo:
        imprimir raiz.valor
        Preorden(raiz.izquierdo)
        Preorden(raiz.derecho)

Recorrido en Profundidad - Postorden (Postorder Traversal):

En el recorrido en profundidad postorden comineza por las hojas, primero se visitan los nodos de los subรกrboles izquierdo y derecho y, finalmente, el nodo raiz. Este enfoque es รบtil para liberar la memoria ocupada por el รกrbol, ya que libera los nodos de abajo hacia arriba. Tambiรฉn se utiliza para realizar operaciones que deben ocurrir despuรฉs de procesar los nodos hijos, como evaluar expresiones aritmรฉticas.

Postorden(raiz):
    si raiz no es nulo:
        Postorden(raiz.izquierdo)
        Postorden(raiz.derecho)
        imprimir raiz.valor

Recorrido en Profundidad - Inoreden (Inorder Traversal):

El recorrido inorden es un tipo de travesรญa en รกrboles que sigue el patrรณn de visitar primero el subรกrbol izquierdo, luego el nodo padre y, finalmente, el subรกrbol derecho. Es especialmente รบtil en รกrboles binarios de bรบsqueda, ya que este orden de recorrido produce una secuencia ordenada de los valores almacenados.

Inorden(nodo):
    si nodo no es nulo:
        Inorden(nodo.izquierdo)
        imprimir nodo.valor
        Inorden(nodo.derecho)

Arboles de busqueda binaria

En esencia, un รกrbol de bรบsqueda binario es una estructura jerรกrquica que consta de nodos, cada uno con, como mรกximo, dos hijos: uno izquierdo y otro derecho. La clave de su eficacia radica en la organizaciรณn de los datos:

  • Los nodos izquierdos tiene un valor inferior que el nodo antedecesor

  • Los nodos derechos tiene un valor mayor que el nodo antedecesor

Operacion de bรบsqueda

La operaciรณn de bรบsqueda en รกrboles de bรบsqueda binarios es una de las funcionalidades clave que hacen que esta estructura de datos sea tan eficiente. El proceso de bรบsqueda se inicia desde la raรญz del รกrbol y avanza hacia abajo, comparando la clave de bรบsqueda con la clave del nodo actual.

  1. Inicio desde la Raรญz:

    • La bรบsqueda comienza en el nodo raรญz del รกrbol. Se compara la clave de bรบsqueda con la clave del nodo actual.

  2. Descenso por el รrbol:

    • Si la clave de bรบsqueda es menor que la clave del nodo actual, la bรบsqueda se dirige hacia el subรกrbol izquierdo. Si es mayor, se dirige hacia el subรกrbol derecho. Este proceso de comparaciรณn y descenso continรบa hasta que se encuentra el nodo deseado o se llega a una hoja del รกrbol, indicando que el elemento no estรก presente.

Funciรณn BuscarEnArbolBinario(raiz, clave):
    Si raiz es nulo o raiz.clave es igual a clave:
        Devolver raiz
    
    Si clave < raiz.clave:
        Devolver BuscarEnArbolBinario(raiz.izquierdo, clave)
    
    Sino:
        Devolver BuscarEnArbolBinario(raiz.derecho, clave)

Operaciรณn de insercion

La operaciรณn de inserciรณn en รกrboles de bรบsqueda binarios es esencial para construir y mantener la estructura del รกrbol de manera ordenada. Aquรญ tienes un pseudocรณdigo bรกsico para la inserciรณn en un รกrbol de bรบsqueda binario:

  1. Caso Base:

    • Si la raรญz es nula, significa que el รกrbol estรก vacรญo, por lo que el nuevo nodo se convierte en la raรญz.

  2. Comparaciรณn de Claves:

    • Se compara la clave del nuevo nodo con la clave del nodo actual. Dependiendo de la comparaciรณn, se decide si se inserta en el subรกrbol izquierdo o derecho.

  3. Recursividad:

    • Si el subรกrbol correspondiente estรก vacรญo, se inserta el nuevo nodo en esa posiciรณn. Si no estรก vacรญo, se realiza la inserciรณn de manera recursiva en el subรกrbol correspondiente.

Funciรณn InsertarEnArbolBinario(raiz, nuevoNodo):
    Si raiz es nula:
        raiz = nuevoNodo
    Sino Si nuevoNodo.clave < raiz.clave:
        Si raiz.izquierdo es nulo:
            raiz.izquierdo = nuevoNodo
        Sino:
            InsertarEnArbolBinario(raiz.izquierdo, nuevoNodo)
    Sino:
        Si raiz.derecho es nulo:
            raiz.derecho = nuevoNodo
        Sino:
            InsertarEnArbolBinario(raiz.derecho, nuevoNodo)

Operaciรณn de eliminiacion

La operaciรณn de eliminaciรณn en รกrboles de bรบsqueda binarios es un proceso mรกs complejo que busca mantener la propiedad de orden del รกrbol mientras se elimina un nodo especรญfico. Aquรญ tienes un pseudocรณdigo bรกsico para la eliminaciรณn en un รกrbol de bรบsqueda binario:

  1. Casos Base:

    • Si la raรญz es nula, significa que el elemento no estรก presente en el รกrbol, por lo que no hay nada que eliminar.

  2. Recursividad:

    • Se realiza la bรบsqueda del nodo a eliminar en el subรกrbol izquierdo o derecho segรบn la comparaciรณn de claves.

  3. Caso 1: Nodo con un solo hijo o sin hijos:

    • Si el nodo a eliminar tiene uno o ningรบn hijo, simplemente se reemplaza por su hijo (si existe) o se elimina directamente.

  4. Caso 2: Nodo con dos hijos:

    • Si el nodo a eliminar tiene dos hijos, se encuentra el sucesor in-order (el nodo mรกs pequeรฑo en el subรกrbol derecho), se copia su clave en el nodo actual y luego se procede a eliminar el sucesor.

    • Es posible hacer lo mismo con el nodo mas grande en el subarbol izquierdo

Funciรณn EliminarEnArbolBinario(raiz, clave):
    Si raiz es nula:
        Devolver raiz
    
    Si clave < raiz.clave:
        raiz.izquierdo = EliminarEnArbolBinario(raiz.izquierdo, clave)
    
    Sino Si clave > raiz.clave:
        raiz.derecho = EliminarEnArbolBinario(raiz.derecho, clave)
    
    Sino:
        // Caso 1: Nodo con un solo hijo o sin hijos
        Si raiz.izquierdo es nulo:
            temp = raiz.derecho
            Eliminar(raiz)
            Devolver temp
        Sino Si raiz.derecho es nulo:
            temp = raiz.izquierdo
            Eliminar(raiz)
            Devolver temp
       
        // Caso 2: Nodo con dos hijos
        temp = EncontrarSucesorInOrder(raiz.derecho)
        raiz.clave = temp.clave
        raiz.derecho = EliminarEnArbolBinario(raiz.derecho, temp.clave)

    Devolver raiz

Este pseudocรณdigo asume funciones auxiliares como Eliminar para eliminar un nodo y EncontrarSucesorInOrder para encontrar el sucesor in-order en el subรกrbol derecho. Asegรบrate de ajustar el pseudocรณdigo segรบn la implementaciรณn especรญfica de tu รกrbol binario. La eliminaciรณn en รกrboles de bรบsqueda binarios garantiza que el รกrbol siga siendo un BST despuรฉs de la operaciรณn.

Last updated