SlideShare una empresa de Scribd logo
1 de 29
en ciencias de la informática, un árbol es una estructura de datos ampliamente
usada que imita la forma de un árbol (un conjunto de nodos conectados).
Un nodo es la unidad sobre la que se construye el árbol y puede tener cero o más
nodos hijos conectados a él. Se dice que un nodo es padre de un nodo si
existe un enlace desde hasta (en ese caso, también decimos que es hijo
de ). Sólo puede haber un único nodo sin padres, que llamaremos raíz. Un nodo
que no tiene hijos se conoce como hoja. Los demás nodos (tienen padre y uno o
varios hijos) se les conoce como rama.

Definición

Formalmente, podemos definir un árbol de la siguiente forma:

      Caso base: un árbol con sólo un nodo (es a la vez raíz del árbol y hoja).

      Un nuevo árbol a partir de un nodo             y   árboles                  de
       raíces                 con                  elementos cada uno, puede
       construirse estableciendo una relación padre-hijo entre     y cada una de
       las      raíces     de     los árboles.       El      árbol      resultante
       de                            nodos tiene como raíz el nodo        , los
       nodos                 son los hijos de  y el conjunto de nodos hoja está
       formado por la unión de los conjuntos hojas iniciales. A cada uno de los
       árboles    se les denota ahorasubárboles de la raíz.

Una sucesión de nodos del árbol, de forma que entre cada dos nodos
consecutivos de la sucesión haya una relación de parentesco, decimos que es
un recorrido árbol. Existen dos recorridos típicos para listar los nodos de un
árbol: primero en profundidad y primero en anchura. En el primer caso, se
listan los nodos expandiendo el hijo actual de cada nodo hasta llegar a una hoja,
donde se vuelve al nodo anterior probando por el siguiente hijo y así
sucesivamente. En el segundo, por su parte, antes de listar los nodos de
nivel        (a distancia       aristas de la raíz), se deben haber listado todos los
de nivel . Otros recorridos típicos del árbol son preorden, postorden e inorden:

      El recorrido en preorden, también llamado orden previo consiste en
       recorrer en primer lugar la raíz y luego cada uno de los hijos
        en orden previo.

      El recorrido en inorden, también llamado orden simétrico (aunque este
       nombre sólo cobra significado en los árboles binarios) consiste en recorrer
       en primer lugar    , luego la raíz y luego cada uno de los hijos
        en orden simétrico.
   El recorrido en postorden, también llamado orden posterior consiste en
       recorrer en primer lugar cada uno de los hijos                 en orden
       posterior y por último la raíz.

Finalmente, puede decirse que esta estructura es una representación del concepto
de árbol en teoría de grafos. Un árbol es un grafo conexo y acíclico.

Operaciones de árboles. Representación




Las rotaciones en árboles binarios son operaciones internas comunes utilizadas
para mantener el balance perfecto (o casi perfecto) del árbol binario. Un árbol
balanceado permite operaciones en tiempo logarítmico.

Las operaciones comunes en árboles son:

      Enumerar todos los elementos.

      Buscar un elemento.

      Dado un nodo, listar los hijos (si los hay).

      Borrar un elemento.

      Eliminar un subárbol (algunas veces llamada podar).

      Añadir un subárbol (algunas veces llamada injertar).

      Encontrar la raíz de cualquier nodo.

Por su parte, la representación puede realizarse de diferentes formas. Las más
utilizadas son:

      Representar cada nodo como una variable en el heap, con punteros a sus
       hijos y a su padre.
   Representar el árbol con un array donde cada elemento es un nodo y las
       relaciones padre-hijo vienen dadas por la posición del nodo en el array.

Uso de los árboles

Usos comunes de los árboles son:

      Representación de datos jerárquicos.

      Como ayuda para realizar búsquedas en conjuntos de datos (ver
       también: algoritmos de búsqueda en Árboles).




Tipos de árboles

      Árboles Binarios

       En ciencias de la computación, un árbol binario es una estructura de
       datos en la cual cada nodo siempre tiene un hijo izquierdo y un hijo
       derecho. No pueden tener más de dos hijos (de ahí el nombre "binario"). Si
       algún hijo tiene como referencia a null, es decir que no almacena ningún
       dato, entonces este es llamado un nodo externo. En el caso contrario el hijo
       es llamado un nodo interno. Usos comunes de los árboles binarios son
       los árboles binarios de búsqueda, los montículos binarios y Codificación de
       Huffman.

       Definición de teoría de grafos




       Un árbol binario sencillo de tamaño 9, 4 niveles y altura 3 (altura = máximo
       nivel - 1), con un nodo raíz cuyo valor es 2.
En teoría de grafos, se usa la siguiente definición: «Un árbol binario es un
    grafo conexo, acíclico y no dirigido tal que el grado de cada vértice no es
    mayor a 3». De esta forma sólo existe un camino entre un par de nodos.

    Un árbol binario con enraizado es como un grafo que tiene uno de sus
    vértices, llamado raíz, de grado no mayor a 2. Con la raíz escogida, cada
    vértice tendrá un único padre, y nunca más de dos hijos. Si rehusamos el
    requerimiento de la conectividad, permitiendo múltiples componentes
    conectados en el grafo, llamaremos a esta última estructura un bosque.

    Tipos de árboles binarios

   Un árbol binario es un árbol con raíz en el que cada nodo tiene como
    máximo dos hijos.

   Un árbol binario lleno es un árbol en el que cada nodo tiene cero o dos
    hijos.

   Un árbol binario perfecto es un árbol binario lleno en el que todas
    las hojas (vértices con cero hijos) están a la misma profundidad (distancia
    desde laraíz, también llamada altura).

   A veces un árbol binario perfecto es denominado árbol binario completo.
    Otros definen un árbol binario completo como un árbol binario lleno en el
    que todas las hojas están a profundidad n o n-1, para alguna n.

    Un árbol binario es un árbol en el que ningún nodo puede tener más de
    dos subárboles. En un árbol binario cada nodo puede tener cero, uno o dos
    hijos (subárboles). Se conoce el nodo de la izquierda como hijo izquierdo y
    el nodo de la derecha como hijo derecho.

    Implementación en C

    Un árbol binario puede declararse de varias maneras. Algunas de ellas son:

    Estructura con manejo de memoria dinámica, siendo puntA el puntero que
    apunta al árbol de tipo tArbol:

    typedefstructnodo {

    int clave;

    struct nodo *izdo, *dcho;

    }Nodo;
Estructura con arreglo indexado:

typedefstructtArbol

{

int clave;

tArbolhIzquierdo, hDerecho;

} tArbol;

tArbol árbol[NUMERO_DE_NODOS];

En el caso de un árbol binario casi-completo (o un árbol completo), puede
utilizarse un sencillo arreglo de enteros con tantas posiciones como nodos
deba tener el árbol. La información de la ubicación del nodo en el árbol es
implícita a cada posición del arreglo. Así, si un nodo está en la posición i,
sus hijos se encuentran en las posiciones 2i+1 y 2i+2, mientras que su
padre (si tiene), se encuentra en la posición truncamiento((i-1)/2)
(suponiendo que la raíz está en la posición cero). Este método se beneficia
de un almacenamiento más compacto y una mejor localidad de referencia,
particularmente durante un recorrido en preorden. La estructura para este
caso sería por tanto:

int árbol[NUMERO_DE_NODOS];

[editar]Recorridos sobre árboles binarios

[editar]Recorridos en profundidad

El método de este recorrido es tratar de encontrar de la cabecera a la raíz
en nodo de unidad binaria. Ahora pasamos a ver la implementación de los
distintos recorridos:

[Recorrido en preorden

En este tipo de recorrido se realiza cierta acción (quizás simplemente
imprimir por pantalla el valor de la clave de ese nodo) sobre el nodo actual y
posteriormente se trata el subárbol izquierdo y cuando se haya concluido, el
subárbol derecho. Otra forma para entender el recorrido con este metodo
seria seguir el orden: nodo raiz, nodo izquierda, nodo derecha.

En el árbol de la figura el recorrido en preorden sería: 2, 7, 2, 6, 5, 11, 5, 9 y
4.
voidpreorden(tArbol *a)

{

if (a != NULL) {

tratar(a);                   //Realiza una operación en nodo

preorden(a->hIzquierdo);

preorden(a->hDerecho);

    }

}

Implementación en pseudocódigo de forma iterativa:

push(s,NULL);       //insertamos en una pila (stack) el valor NULL, para
asegurarnos de que esté vacía

push(s,raíz);                   //insertamos el nodo raíz

MIENTRAS (s <> NULL) HACER

        p = pop(s);            //sacamos un elemento de la pila

tratar(p);                  //realizamos operaciones sobre el nodo p

        SI (D(p) <> NULL)          //preguntamos si p tiene árbol derecho

ENTONCES push(s,D(p));

FIN-SI

        SI (I(p) <> NULL)         //preguntamos si p tiene árbol izquierdo

ENTONCES push(s,I(p));

FIN-SI

FIN-MIENTRAS

[editar]Recorrido en postorden

En este caso se trata primero el subárbol izquierdo, después el derecho y
por último el nodo actual. Otra forma para entender el recorrido con este
metodo seria seguir el orden: nodo izquierda, nodo derecha, nodo raiz. En
el árbol de la figura el recorrido en postorden sería: 2, 5, 11, 6, 7, 4, 9, 5 y 2.
voidpostorden(tArbol *a)

{

if (a != NULL) {

postorden(a->hIzquiedo);

postorden(a->hDerecho);

tratar(a);                //Realiza una operación en nodo

    }

}

Recorrido en inorden

En este caso se trata primero el subárbol izquierdo, después el nodo actual
y por último el subárbol derecho. En un ABB este recorrido daría los valores
de clave ordenados de menor a mayor. Otra forma para entender el
recorrido    con     este    metodo        seria seguir el  orden:     nodo
izquierda,nodoraiz,nodo derecha. En el árbol de la figura el recorrido en
inorden sería: 2, 7, 5, 6, 11, 2, 5, 4, 9.

Esquema de implementación:

voidinorden(tArbol *a)

{

if (a != NULL) {

inorden(a->hIzquierdo);

tratar(a);                     //Realiza una operación en nodo

inorden(a->hDerecho);

    }

}

Recorridos en amplitud (o por niveles)

En este caso el recorrido se realiza en orden por los distintos niveles del
árbol. Así, se comenzaría tratando el nivel 1, que sólo contiene el nodo raíz,
seguidamente el nivel 2, el 3 y así sucesivamente. En el árbol de la figura el
recorrido en amplitud sería: 2, 7, 5, 2, 6, 9, 5, 11 y 4.

Al contrario que en los métodos de recorrido en profundidad, el recorrido
por niveles no es de naturaleza recursiva. Por ello, se debe utilizar una cola
para recordar los subárboles izquierdos y derecho de cada nodo.

El esquema algoritmo para implementar un recorrido por niveles es
exactamente el mismo que el utilizado en la versión iterativa del recorrido
en preorden pero cambiando la estructura de datos que almacena los
nodos por una cola.

Implementación en C:

voidarbol_recorrido_anch (tipo_Arbol* A) {

tipo_Colacola_nodos; // esta cola esta implementada previamente,
almacena punteros (posiciones de nodos de árbol)



tipo_Posnodo_actual; // este es un puntero llevara el recorrido



if (vacio(A)) // si el árbol esta vacio, salimos

return;



cola_inicializa(&cola_nodos); // obvio, y necesario



cola_enqueue(A, &cola_nodos); // se encola la raiz



while (!vacia(&cola_nodos)) { // mientras la cola no se vacie se realizara el
recorrido

nodo_actual = cola_dequeue(&cola_nodos) // de la cola saldran los nodos
ordenados por nivel
printf("%c,", nodo_actual->info); // se "procesa" el nodo donde va el
recorrido, en este caso se imprime



if (nodo_actual->izq != null) // si existe, ponemos el hijo izquierdo en la cola

cola_enqueue(nodo_actual->izq, &cola_nodos);



if (nodo_actual->der != null) // si existe, ponemos el hijo derecho en la cola

cola_enqueue(nodo_actual->der, &cola_nodos);



      } // al vaciarse la cola se han visitado todos los nodos del árbol

  }

Métodos para almacenar árboles binarios

Los árboles binarios pueden ser construidos a partir de lenguajes de
programación de varias formas. En un lenguaje con registros y referencias,
los árboles binarios son construidos típicamente con una estructura de
nodos y punteros en la cual se almacenan datos, cada uno de estos nodos
tiene una referencia o puntero a un nodo izquierdo y a un nodo derecho
denominados hijos. En ocasiones, también contiene un puntero a un único
nodo. Si un nodo tiene menos de dos hijos, algunos de los punteros de los
hijos pueden ser definidos como nulos para indicar que no dispone de dicho
nodo. En la figura adjunta se puede observar la estructura de dicha
implementación.
Los árboles binarios también pueden ser almacenados como una estructura
de datos implícita en vectores, y si el árbol es un árbol binario completo,
este método no desaprovecha el espacio en memoria. Tomaremos como
notación la siguiente: si un nodo tiene un índice i, sus hijos se encuentran
en índices 2i + 1 y 2i + 2, mientras que sus padres (si los tiene) se


encuentra en el índice       (partiendo de que la raíz tenga índice cero).
Este método tiene como ventajas el tener almacenados los datos de forma
más compacta y por tener una forma más rápida y eficiente de localizar los
datos en particular durante un preoden transversal. Sin embargo,
desperdicia mucho espacio en memoria.




Codificación de árboles n-arios como árboles binarios

Hay un mapeo uno a uno entre los árboles generales y árboles binarios, el
cual en particular es usado en Lisp para representar árboles generales
como árboles binarios. Cada nodo N ordenado en el árbol corresponde a un
nodo N' en el árbol binario; el hijo de la izquierda de N’ es el nodo
correspondiente al primer hijo de N, y el hijo derecho de N' es el nodo
correspondiente al siguiente hermano de N, es decir, el próximo nodo en
orden entre los hijos de los padres de N.

Esta representación como árbol binario de un árbol general, se conoce a
veces como un árbol binario primer hijo hermano, o un árbol doblemente
encadenado.

Una manera de pensar acerca de esto es que los hijos de cada nodo estén
en una lista enlazada, encadenados junto con el campo derecho, y el nodo
sólo tiene un puntero al comienzo o la cabeza de esta lista, a través de su
campo izquierdo.

Por ejemplo, en el árbol de la izquierda, la A tiene 6 hijos (B, C, D, E, F, G).
Puede ser convertido en el árbol binario de la derecha.

Un ejemplo de transformar el árbol n-ario a un árbol binario cómo pasar de
árboles n-arios a árboles FLOFO.
El árbol binario puede ser pensado como el árbol original inclinado hacia los
      lados, con los bordes negros izquierdos representando el primer hijo y los
      azules representado los siguientes hermanos.

      Las hojas del árbol de la izquierda serían escritas en Lisp como:

        (((N O) I J) C D ((P) (Q)) F (M))

      Que se ejecutará en la memoria como el árbol binario de la derecha, sin
      ningún tipo de letras en aquellos nodos que tienen un hijo izquierdo.

                   Árboles AVL

Árbol avl es un tipo especial de árbol binario ideado por los matemáticos
rusos Adelson-Velskii y Landis. Fue el primer árbol de búsqueda binario auto-
balanceable que se ideó.

Descripción
Un ejemplo de árbol binario no equilibrado(no es AVL)




Un ejemplo de árbol binario equilibrado (si es AVL)

El árbol AVL toma su nombre de las iniciales de los apellidos de sus
inventores, Adelson-Velskii y Landis. Lo dieron a conocer en la publicación de un
artículo en 1962: "Analgorithmfortheorganization of information" ("Un algoritmo
para la organización de la información").

Los árboles AVL están siempre equilibrados de tal modo que para todos los
nodos, la altura de la rama izquierda no difiere en más de una unidad de la altura
de la rama derecha o viceversa. Gracias a esta forma de equilibrio (o balanceo), la
complejidad de una búsqueda en uno de estos árboles se mantiene siempre en
orden de complejidad O(log n). El factor de equilibrio puede ser almacenado
directamente en cada nodo o ser computado a partir de las alturas de los
subárboles.

Para conseguir esta propiedad de equilibrio, la inserción y el borrado de los nodos
se ha de realizar de una forma especial. Si al realizar una operación de inserción o
borrado se rompe la condición de equilibrio, hay que realizar una serie
de rotaciones de los nodos.

Los árboles AVL más profundos son los árboles de Fibonacci.

[Definición formal

[editar]Definición de la altura de un árbol

Sea      un árbol     binario   de   búsqueda y   sean   y     sus   subárboles,   su
altura        , es:

         si el árbol    contiene solo la raíz

                                      si contiene más nodos
[editar]Definición de árbol AVL

      Un árbol vacío es un árbol AVL

      Si es un árbol no vacío y       y    sus subárboles, entonces    es AVL si y
       solo si:

         es AVL

          es AVL

   

[editar]Factor de equilibrio

Cada nodo, además de la información que se pretende almacenar, debe tener los
dos punteros a los árboles derecho e izquierdo, igual que los árboles binarios de
búsqueda (ABB), y además el dato que controla el factor de equilibrio.

El factor de equilibrio es la diferencia entre las alturas del árbol derecho y el
izquierdo:

FE = altura subárbol derecho - altura subárbol izquierdo;

Por definición, para un árbol AVL, este valor debe ser -1, 0 ó 1.

Si el factor de equilibrio de un nodo es:

0 -> el nodo está equilibrado y sus subárboles tienen exactamente la misma altura.

1 -> el nodo está desequilibrado y su subárbol derecho es un nivel más alto.

-1 -> el nodo está desequilibrado y su subárbol izquierdo es un nivel más alto.

Si el factor de equilibrio            es necesario reequilibrar.

[editar]Operaciones

Las operaciones básicas de un árbol AVL implican generalmente el realizar los
mismos algoritmos que serían realizados en un árbol binario de
búsqueda desequilibrado, pero precedido o seguido por una o más de las
llamadas "rotaciones AVL".
Rotaciones




Las rotaciones internas en árboles binarios son operaciones internas comunes
utilizadas para mantener el balance perfecto (o casi perfecto del árbol binario. Un
árbol balanceado permite operaciones en tiempo logarítmico

El reequilibrado se produce de abajo hacia arriba sobre los nodos en los que se
produce el desequilibrio. Pueden darse dos casos: rotación simple o rotación
doble; a su vez ambos casos pueden ser hacia la derecha o hacia la izquierda.

ROTACIÓN SIMPLE A LA DERECHA.

De un árbol de raíz (r) y de hijos izquierdo (i) y derecho (d), lo que haremos será
formar un nuevo árbol cuya raíz sea la raíz del hijo izquierdo, como hijo izquierdo
colocamos el hijo izquierdo de i (nuestro i’) y como hijo derecho construimos un
nuevo árbol que tendrá como raíz, la raíz del árbol (r), el hijo derecho de i (d’) será
el hijo izquierdo y el hijo derecho será el hijo derecho del árbol (d).




oprotDer: AVL{X} -> [AVL{X}] .

eqrotDer(arbolBin(R1, arbolBin(R2, I2, D2), D1)) ==
arbolBin(R2, I2, arbolBin(R1, D2, D)) .

ROTACIÓN SIMPLE A LA IZQUIERDA.

De un árbol de raíz (r) y de hijos izquierdo (i) y derecho (d), consiste en formar un
nuevo árbol cuya raíz sea la raíz del hijo derecho, como hijo derecho colocamos el
hijo derecho de d (nuestro d’) y como hijo izquierdo construimos un nuevo árbol
que tendrá como raíz la raíz del árbol (r), el hijo izquierdo de d será el hijo derecho
(i’) y el hijo izquierdo será el hijo izquierdo del árbol (i).

Precondición : Tiene que tener hijo derecho no vacío.




oprotIzq: AVL{X} -> [AVL{X}] .

eqrotIzq(arbolBin(R1, I, arbolBin(R2, I2, D2))) ==

arbolBin(R2, arbolBin(R1, I, I2), D2) .



Si la inserción se produce en el hijo derecho del hijo izquierdo del nodo
desequilibrado (o viceversa) hay que realizar una doble rotación.
ROTACIÓN DOBLE A LA DERECHA.


La Rotación doble a la Derecha son dos rotaciones simples, primero rotacion
simple izquierda y luego rotación simple derecha.




ROTACIÓN              DOBLE               A        LA            IZQUIERDA.
La Rotación doble a la Izquierda son dos rotaciones simples, primero rotacion
simple derecha y luego rotación simple izquierda.
Inserción

La inserción en un árbol de AVL puede ser realizada insertando el valor dado en el
árbol como si fuera un árbol de búsqueda binario desequilibrado y después
retrocediendo hacia la raíz, rotando sobre cualquier nodo que pueda haberse
desequilibrado durante la inserción.

Proceso de inserción:

1.buscar hasta encontrar la posición de inserción o modificación (proceso idéntico
a inserción en árbol binario de búsqueda)

2.insertar el nuevo nodo con factor de equilibrio “equilibrado”

3.desandar el camino de búsqueda, verificando el equilibrio de los nodos, y re-
equilibrando si es necesario
Debido a que las rotaciones son una operación que tienen complejidad constante
y a que la altura esta limitada a O (log(n)), el tiempo de ejecución para la inserción
es del orden O (log(n)).
opinsertar: X$Elt AVL{X} -> AVLNV{X} .

eq insertar(R, crear) == arbolBin(R, crear, crear) .

ceqinsertar(R1, arbolBin(R2, I, D)) ==

if (R1==R2) then

arbolBin(R2, I, D)

elseif (R1<R2) then

if ( (altura(insertar(R1,I)) – altura(D)) < 2) then

arbolBin(R2, insertar(R1, I), D)

else ***hay que reequilibrar

if (R1 <raiz(I)) then

rotarDer(arbolBin(R2, insertar(R1, I), D))

else

rotarDer(arbolBin(R2, rotarIzq(insertar(R1, I)), D))

fi .

fi .

else

if ( (altura(insertar(R1,I)) – altura(D)) < 2) then

arbolBin(R2, insertar(R1, I), D)

else *** hay que reequilibrar

if (R1 >raiz(D)) then

rotarIzq(arbolBin(R, I, insertar(R1, D)))

else

rotatIzq(arbolBin(R, I, rotarDer(insertar(R1, D))))

fi .

fi .
fi .



Extracción

El procedimiento de borrado es el mismo que en el caso de árbol binario de
búsqueda.La diferencia se encuentra en el proceso de reequilibrado posterior. El
problema de la extracción puede resolverse en O (log n) pasos. Una extracción
trae consigo una disminución de la altura de la rama donde se extrajo y tendrá
como efecto un cambio en el factor de equilibrio del nodo padre de la rama en
cuestión, pudiendo necesitarse una rotación.

Esta disminución de la altura y la corrección de los factores de equilibrio con sus
posibles rotaciones asociadas pueden propagarse hasta la raíz.




                          Borrar A, y la nueva raíz será M.




                        Borrado A, la nueva raíz es M. Aplicamos la rotación a la
derecha.
El árbol resultante ha perdido altura.

En borrado pueden ser necesarias varias operaciones de restauración del
equilibrio, y hay que seguir comprobando hasta llegar a la raíz.



opeliminar: X$Elt AVL{X} -> AVL{X} .

eq eliminar(R, crear) == crear .

ceqeliminar(R1, arbolBin(R2, I, D)) ==

if (R1 == R2) then

ifesVacio(I) then

                D

elseifesVacio(D) then

                I

else

if (altura(I) - altura(eliminar(min(D),D)) < 2) then

arbolBin(min(D), I, eliminar(min(D), D))

                ***tenemos que reequilibrar

elseif (altura(hijoIzq(I) >= altura(hijoDer(I)))) then

rotDer(arbolBin(min(D), I, eliminar(min(D),D)))

else

rotDer(arbolBin(min(D), rotIzq(I), eliminar(min(D),D)))
Búsqueda

Ejemplo de TAD AVL en C

#include <stdio.h>



typedefstruct AVL{

int dato, FB; // FB es la altura del subarbol izquierdo menos la altura del subarbol
derecho

     AVL *izq, *der;

bool borrado;

} AVL;



voidrotarLL(AVL* &A){ //precond: el arbol necesita una rotacion LL

     AVL* aux = A->izq->der;

     A->izq->der = A;

     A->izq->FB = 0;

     AVL* aux2 = A->izq;

     A->izq = aux;

     A->FB = 0;

     A = aux2;

}



voidrotarRR(AVL* &A){ //precond: el arbol necesita una rotacion RR

     AVL* aux = A->der->izq;

     A->der->izq = A;

     A->der->FB = 0;
AVL* aux2 = A->der;

     A->der = aux;

     A->FB = 0;

     A = aux2;

}



voidrotarLRalter(AVL* &A){ //precond: el arbol necesita una rotacion LR

rotarRR(A->izq);

rotarLL(A);

}



voidrotarRLalter(AVL* &A){ //precond: el arbol necesita una rotacion RL

rotarLL(A->der);

rotarRR(A);

}



AVL* Crear(){

return NULL;

}



void Insert(int n, bool&aumento, AVL* &A){

if (A == NULL){

          A = new AVL;

A->dato = n;

          A->FB = 0;
A->izq = NULL;

            A->der = NULL;

aumento = true;

            A->borrado = false;

}else{

if (n < A->dato){

Insert(n, aumento, A->izq);

if (aumento){

switch (A->FB){

case -1:{

                                  A->FB = 0;

aumento = false;

break;

                          }

case 0:{

                                  A->FB = 1;

aumento = true;

break;

                          }

case 1:{

if (A->izq->FB == 1){ // Si es 1 necesita una rotacion LL si es -1 necesita una
rotacion LR

rotarLL(A);

                                  }else{

rotarLRalter(A);
}

aumento = false;

break;

                        }

                    }

                }

}else{

Insert(n, aumento, A->der);

if (aumento){

switch (A->FB){

case -1:{

if (A->der->FB == 1){ // Si es 1 necesita una rotacion RL si es -1 necesita una
rotacion RR

rotarRLalter(A);

                              }else{

rotarRR(A);

                              }

aumento = false;

break;

                        }

case 0:{

                              A->FB = -1;

aumento = true;

break;

                        }
case 1:{

                                 A->FB = 0;

aumento = false;

break;

                         }

                     }

                }

           }

     }

}



void Insertar(AVL* &A, int n){

bool aumento;

Insert(n, aumento, A);

}



boolEsVacio(AVL* A){

return A == NULL;

}



bool Pertenece(AVL* A, int n){

if (A == NULL){

returnfalse;

     }else{

if (A->dato == n){
if (A->borrado){

returnfalse;

}else{

returntrue;

                }

}else if (n < A->dato){

return Pertenece(A->izq, n);

          }else{

return Pertenece(A->der, n);

          }

     }

}



void Borrar(AVL* &A, int n){

if (A->dato == n){

          A->borrado = true;

}else if (n < A->dato){

Borrar(A->izq, n);

     }else{

          Borrar(A->der, n);

     }

}



                       Árboles Rojo-Negro

                       Árbol AA
   Árboles Multicamino

             Árboles B (Arboles de búsqueda multicaminoautobalanceados)

                      Árbol-B+

                      Árbol-B*

Árbol (teoría de grafos)

Para otros usos de este término, véase Árbol (desambiguación).

En teoría de grafos, un árbol es un grafo en el que cualesquiera
dos vértices están conectados por exactamente un camino. Un bosque es una
unión disjunta de árboles. Un árbol a veces recibe el nombre de árbol libre.

[editar]Definiciones

Un árbol es un grafo simple unidireccional G que satisface alguna de las
siguientes condiciones equivalentes:

      G es conexo y no tiene ciclos .

      G no tiene ciclos y, si se añade alguna arista se forma un ciclo.

      G es conexo y si se le quita alguna arista deja de ser conexo.

      G es conexo y el grafo completo de 3 vértices      no es un menor de G.

      Dos vértices cualquiera de G están conectados por un único camino simple.

Si G tiene muchos vértices, n, entonces las definiciones anteriores son también
equivalentes a cualquiera de las siguientes condiciones:

      G es conexo y tiene n − 1 aristas.

      G es conexo y sin ciclos .

      Cualesquiera 2 vértices están unidos por una única trayectoria.



un grafo unidireccional simple G es un bosque si no tiene ciclos simples.

Un árbol dirigido es un grafo dirigido que sería un árbol si no se consideraran las
direcciones de las aristas. Algunos autores restringen la frase al caso en el que
todos las aristas se dirigen a un vértice particular, o todas sus direcciones parten
de un vértice particular.
Un árbol recibe el nombre de árbol con raíz si cada vértice ha sido designado raíz,
en cuyo caso las aristas tienen una orientación natural hacia odesde la raíz. Los
árboles con raíz, a menudo con estructuras adicionales como orden de los vecinos
de cada vértice, son una estructura clave en informática; véase árbol
(programación).

Un árbol etiquetado es un árbol en el que cada vértice tiene una única etiqueta.
Los vértices de un árbol etiquetado de n vértices reciben normalmente las
etiquetas {1,2, ..., n}.

Un árbol regular u homogéneo es un árbol en el que cada vértice tiene el
mismo grado.

[editar]Propiedades

Todo árbol es a su vez un grafo bipartito. Todo árbol con sólo un conjunto
numerable de vértices es además un grafo plano.

Todo grafo conexo G admite un árbol de expansión, que es un árbol que contiene
cada vértice de G y cuyas aristas son aristas de G.

Dado n vértices etiquetados, hay n n−2 maneras diferentes de conectarlos para
construir un grafo. El resultado se llama fórmula de Cayley. El número de árboles
con n vértices de gradod1,d2,...,dn es:




que es un coeficiente multinomial.

Contar el número de árboles no etiquetados es un problema complicado. De
hecho, no se conoce ninguna fórmula para el número de árboles t(n)
con n vértices (debe entederse aquí el número de árboles diferentes salvo
isomorfismo de grafos). Los primeros valores de t(n) son 1, 1, 1, 1, 2, 3, 6, 11, 23,
47, 106, 235, 551, 1301, 3159, ... (sucesión A000055 en OEIS). Otter (1948) probó
que



Una fórmula más exacta para el comportamiento asintótico de t(n) implica que hay
dos números α y β (α ≈ 3 y β ≈ 0.5) tales que:

Más contenido relacionado

La actualidad más candente

La actualidad más candente (19)

ARBOLES BINARIOS
ARBOLES BINARIOSARBOLES BINARIOS
ARBOLES BINARIOS
 
Arboles
ArbolesArboles
Arboles
 
Arboles
Arboles Arboles
Arboles
 
Arboles02
Arboles02Arboles02
Arboles02
 
Arboles binarios
Arboles binariosArboles binarios
Arboles binarios
 
Estructuras No Lineales
Estructuras No LinealesEstructuras No Lineales
Estructuras No Lineales
 
Árboles binarios, ABB y AVL
Árboles binarios, ABB y AVLÁrboles binarios, ABB y AVL
Árboles binarios, ABB y AVL
 
arboles avl con codigo en java
arboles avl con codigo en javaarboles avl con codigo en java
arboles avl con codigo en java
 
Programación 3: árboles binarios y ordenados
Programación 3: árboles binarios y ordenadosProgramación 3: árboles binarios y ordenados
Programación 3: árboles binarios y ordenados
 
Arboles En Estructura de Datos
Arboles En Estructura de DatosArboles En Estructura de Datos
Arboles En Estructura de Datos
 
Diapositiva de prueba
Diapositiva de pruebaDiapositiva de prueba
Diapositiva de prueba
 
Ordenamiento con árbol binario
Ordenamiento con árbol binarioOrdenamiento con árbol binario
Ordenamiento con árbol binario
 
C11.1. árboles
C11.1. árbolesC11.1. árboles
C11.1. árboles
 
Arboles binarios
Arboles binariosArboles binarios
Arboles binarios
 
Arboles v2
Arboles v2Arboles v2
Arboles v2
 
Arboles
ArbolesArboles
Arboles
 
Arboles
ArbolesArboles
Arboles
 
Arboles balanceados
Arboles balanceadosArboles balanceados
Arboles balanceados
 
ARBOLES
ARBOLESARBOLES
ARBOLES
 

Similar a Para leer estructuras (20)

estructura de árbol.pdf JOSE GABRIEL LUCENA
estructura de árbol.pdf JOSE GABRIEL LUCENAestructura de árbol.pdf JOSE GABRIEL LUCENA
estructura de árbol.pdf JOSE GABRIEL LUCENA
 
Declarar Arboles. Operaciones. Ejemplospdf
Declarar Arboles. Operaciones. EjemplospdfDeclarar Arboles. Operaciones. Ejemplospdf
Declarar Arboles. Operaciones. Ejemplospdf
 
Arboles
ArbolesArboles
Arboles
 
Arboles
ArbolesArboles
Arboles
 
Arboles TDAS
Arboles TDASArboles TDAS
Arboles TDAS
 
DECLARACION DE ARBOLES.pdf
DECLARACION DE ARBOLES.pdfDECLARACION DE ARBOLES.pdf
DECLARACION DE ARBOLES.pdf
 
Arboles
ArbolesArboles
Arboles
 
Informe de Arboles.pdf
Informe de Arboles.pdfInforme de Arboles.pdf
Informe de Arboles.pdf
 
Arboles mate discreta
Arboles mate discretaArboles mate discreta
Arboles mate discreta
 
Arboles 2c realizado.pptx
Arboles 2c realizado.pptxArboles 2c realizado.pptx
Arboles 2c realizado.pptx
 
Arboles multicamino
Arboles  multicaminoArboles  multicamino
Arboles multicamino
 
Estructura de datos
Estructura de datosEstructura de datos
Estructura de datos
 
Sustentacion arboles
Sustentacion arbolesSustentacion arboles
Sustentacion arboles
 
tema4.pdf
tema4.pdftema4.pdf
tema4.pdf
 
arbol.pdf
arbol.pdfarbol.pdf
arbol.pdf
 
Dylan_Medina_Arbol.pdf
Dylan_Medina_Arbol.pdfDylan_Medina_Arbol.pdf
Dylan_Medina_Arbol.pdf
 
Arboles.pptx
Arboles.pptxArboles.pptx
Arboles.pptx
 
Declaracion de arboles David Ratmiroff.pdf
Declaracion de arboles David Ratmiroff.pdfDeclaracion de arboles David Ratmiroff.pdf
Declaracion de arboles David Ratmiroff.pdf
 
Arboles
ArbolesArboles
Arboles
 
Arboles
ArbolesArboles
Arboles
 

Para leer estructuras

  • 1. en ciencias de la informática, un árbol es una estructura de datos ampliamente usada que imita la forma de un árbol (un conjunto de nodos conectados). Un nodo es la unidad sobre la que se construye el árbol y puede tener cero o más nodos hijos conectados a él. Se dice que un nodo es padre de un nodo si existe un enlace desde hasta (en ese caso, también decimos que es hijo de ). Sólo puede haber un único nodo sin padres, que llamaremos raíz. Un nodo que no tiene hijos se conoce como hoja. Los demás nodos (tienen padre y uno o varios hijos) se les conoce como rama. Definición Formalmente, podemos definir un árbol de la siguiente forma:  Caso base: un árbol con sólo un nodo (es a la vez raíz del árbol y hoja).  Un nuevo árbol a partir de un nodo y árboles de raíces con elementos cada uno, puede construirse estableciendo una relación padre-hijo entre y cada una de las raíces de los árboles. El árbol resultante de nodos tiene como raíz el nodo , los nodos son los hijos de y el conjunto de nodos hoja está formado por la unión de los conjuntos hojas iniciales. A cada uno de los árboles se les denota ahorasubárboles de la raíz. Una sucesión de nodos del árbol, de forma que entre cada dos nodos consecutivos de la sucesión haya una relación de parentesco, decimos que es un recorrido árbol. Existen dos recorridos típicos para listar los nodos de un árbol: primero en profundidad y primero en anchura. En el primer caso, se listan los nodos expandiendo el hijo actual de cada nodo hasta llegar a una hoja, donde se vuelve al nodo anterior probando por el siguiente hijo y así sucesivamente. En el segundo, por su parte, antes de listar los nodos de nivel (a distancia aristas de la raíz), se deben haber listado todos los de nivel . Otros recorridos típicos del árbol son preorden, postorden e inorden:  El recorrido en preorden, también llamado orden previo consiste en recorrer en primer lugar la raíz y luego cada uno de los hijos en orden previo.  El recorrido en inorden, también llamado orden simétrico (aunque este nombre sólo cobra significado en los árboles binarios) consiste en recorrer en primer lugar , luego la raíz y luego cada uno de los hijos en orden simétrico.
  • 2. El recorrido en postorden, también llamado orden posterior consiste en recorrer en primer lugar cada uno de los hijos en orden posterior y por último la raíz. Finalmente, puede decirse que esta estructura es una representación del concepto de árbol en teoría de grafos. Un árbol es un grafo conexo y acíclico. Operaciones de árboles. Representación Las rotaciones en árboles binarios son operaciones internas comunes utilizadas para mantener el balance perfecto (o casi perfecto) del árbol binario. Un árbol balanceado permite operaciones en tiempo logarítmico. Las operaciones comunes en árboles son:  Enumerar todos los elementos.  Buscar un elemento.  Dado un nodo, listar los hijos (si los hay).  Borrar un elemento.  Eliminar un subárbol (algunas veces llamada podar).  Añadir un subárbol (algunas veces llamada injertar).  Encontrar la raíz de cualquier nodo. Por su parte, la representación puede realizarse de diferentes formas. Las más utilizadas son:  Representar cada nodo como una variable en el heap, con punteros a sus hijos y a su padre.
  • 3. Representar el árbol con un array donde cada elemento es un nodo y las relaciones padre-hijo vienen dadas por la posición del nodo en el array. Uso de los árboles Usos comunes de los árboles son:  Representación de datos jerárquicos.  Como ayuda para realizar búsquedas en conjuntos de datos (ver también: algoritmos de búsqueda en Árboles). Tipos de árboles  Árboles Binarios En ciencias de la computación, un árbol binario es una estructura de datos en la cual cada nodo siempre tiene un hijo izquierdo y un hijo derecho. No pueden tener más de dos hijos (de ahí el nombre "binario"). Si algún hijo tiene como referencia a null, es decir que no almacena ningún dato, entonces este es llamado un nodo externo. En el caso contrario el hijo es llamado un nodo interno. Usos comunes de los árboles binarios son los árboles binarios de búsqueda, los montículos binarios y Codificación de Huffman. Definición de teoría de grafos Un árbol binario sencillo de tamaño 9, 4 niveles y altura 3 (altura = máximo nivel - 1), con un nodo raíz cuyo valor es 2.
  • 4. En teoría de grafos, se usa la siguiente definición: «Un árbol binario es un grafo conexo, acíclico y no dirigido tal que el grado de cada vértice no es mayor a 3». De esta forma sólo existe un camino entre un par de nodos. Un árbol binario con enraizado es como un grafo que tiene uno de sus vértices, llamado raíz, de grado no mayor a 2. Con la raíz escogida, cada vértice tendrá un único padre, y nunca más de dos hijos. Si rehusamos el requerimiento de la conectividad, permitiendo múltiples componentes conectados en el grafo, llamaremos a esta última estructura un bosque. Tipos de árboles binarios  Un árbol binario es un árbol con raíz en el que cada nodo tiene como máximo dos hijos.  Un árbol binario lleno es un árbol en el que cada nodo tiene cero o dos hijos.  Un árbol binario perfecto es un árbol binario lleno en el que todas las hojas (vértices con cero hijos) están a la misma profundidad (distancia desde laraíz, también llamada altura).  A veces un árbol binario perfecto es denominado árbol binario completo. Otros definen un árbol binario completo como un árbol binario lleno en el que todas las hojas están a profundidad n o n-1, para alguna n. Un árbol binario es un árbol en el que ningún nodo puede tener más de dos subárboles. En un árbol binario cada nodo puede tener cero, uno o dos hijos (subárboles). Se conoce el nodo de la izquierda como hijo izquierdo y el nodo de la derecha como hijo derecho. Implementación en C Un árbol binario puede declararse de varias maneras. Algunas de ellas son: Estructura con manejo de memoria dinámica, siendo puntA el puntero que apunta al árbol de tipo tArbol: typedefstructnodo { int clave; struct nodo *izdo, *dcho; }Nodo;
  • 5. Estructura con arreglo indexado: typedefstructtArbol { int clave; tArbolhIzquierdo, hDerecho; } tArbol; tArbol árbol[NUMERO_DE_NODOS]; En el caso de un árbol binario casi-completo (o un árbol completo), puede utilizarse un sencillo arreglo de enteros con tantas posiciones como nodos deba tener el árbol. La información de la ubicación del nodo en el árbol es implícita a cada posición del arreglo. Así, si un nodo está en la posición i, sus hijos se encuentran en las posiciones 2i+1 y 2i+2, mientras que su padre (si tiene), se encuentra en la posición truncamiento((i-1)/2) (suponiendo que la raíz está en la posición cero). Este método se beneficia de un almacenamiento más compacto y una mejor localidad de referencia, particularmente durante un recorrido en preorden. La estructura para este caso sería por tanto: int árbol[NUMERO_DE_NODOS]; [editar]Recorridos sobre árboles binarios [editar]Recorridos en profundidad El método de este recorrido es tratar de encontrar de la cabecera a la raíz en nodo de unidad binaria. Ahora pasamos a ver la implementación de los distintos recorridos: [Recorrido en preorden En este tipo de recorrido se realiza cierta acción (quizás simplemente imprimir por pantalla el valor de la clave de ese nodo) sobre el nodo actual y posteriormente se trata el subárbol izquierdo y cuando se haya concluido, el subárbol derecho. Otra forma para entender el recorrido con este metodo seria seguir el orden: nodo raiz, nodo izquierda, nodo derecha. En el árbol de la figura el recorrido en preorden sería: 2, 7, 2, 6, 5, 11, 5, 9 y 4.
  • 6. voidpreorden(tArbol *a) { if (a != NULL) { tratar(a); //Realiza una operación en nodo preorden(a->hIzquierdo); preorden(a->hDerecho); } } Implementación en pseudocódigo de forma iterativa: push(s,NULL); //insertamos en una pila (stack) el valor NULL, para asegurarnos de que esté vacía push(s,raíz); //insertamos el nodo raíz MIENTRAS (s <> NULL) HACER p = pop(s); //sacamos un elemento de la pila tratar(p); //realizamos operaciones sobre el nodo p SI (D(p) <> NULL) //preguntamos si p tiene árbol derecho ENTONCES push(s,D(p)); FIN-SI SI (I(p) <> NULL) //preguntamos si p tiene árbol izquierdo ENTONCES push(s,I(p)); FIN-SI FIN-MIENTRAS [editar]Recorrido en postorden En este caso se trata primero el subárbol izquierdo, después el derecho y por último el nodo actual. Otra forma para entender el recorrido con este metodo seria seguir el orden: nodo izquierda, nodo derecha, nodo raiz. En el árbol de la figura el recorrido en postorden sería: 2, 5, 11, 6, 7, 4, 9, 5 y 2.
  • 7. voidpostorden(tArbol *a) { if (a != NULL) { postorden(a->hIzquiedo); postorden(a->hDerecho); tratar(a); //Realiza una operación en nodo } } Recorrido en inorden En este caso se trata primero el subárbol izquierdo, después el nodo actual y por último el subárbol derecho. En un ABB este recorrido daría los valores de clave ordenados de menor a mayor. Otra forma para entender el recorrido con este metodo seria seguir el orden: nodo izquierda,nodoraiz,nodo derecha. En el árbol de la figura el recorrido en inorden sería: 2, 7, 5, 6, 11, 2, 5, 4, 9. Esquema de implementación: voidinorden(tArbol *a) { if (a != NULL) { inorden(a->hIzquierdo); tratar(a); //Realiza una operación en nodo inorden(a->hDerecho); } } Recorridos en amplitud (o por niveles) En este caso el recorrido se realiza en orden por los distintos niveles del árbol. Así, se comenzaría tratando el nivel 1, que sólo contiene el nodo raíz,
  • 8. seguidamente el nivel 2, el 3 y así sucesivamente. En el árbol de la figura el recorrido en amplitud sería: 2, 7, 5, 2, 6, 9, 5, 11 y 4. Al contrario que en los métodos de recorrido en profundidad, el recorrido por niveles no es de naturaleza recursiva. Por ello, se debe utilizar una cola para recordar los subárboles izquierdos y derecho de cada nodo. El esquema algoritmo para implementar un recorrido por niveles es exactamente el mismo que el utilizado en la versión iterativa del recorrido en preorden pero cambiando la estructura de datos que almacena los nodos por una cola. Implementación en C: voidarbol_recorrido_anch (tipo_Arbol* A) { tipo_Colacola_nodos; // esta cola esta implementada previamente, almacena punteros (posiciones de nodos de árbol) tipo_Posnodo_actual; // este es un puntero llevara el recorrido if (vacio(A)) // si el árbol esta vacio, salimos return; cola_inicializa(&cola_nodos); // obvio, y necesario cola_enqueue(A, &cola_nodos); // se encola la raiz while (!vacia(&cola_nodos)) { // mientras la cola no se vacie se realizara el recorrido nodo_actual = cola_dequeue(&cola_nodos) // de la cola saldran los nodos ordenados por nivel
  • 9. printf("%c,", nodo_actual->info); // se "procesa" el nodo donde va el recorrido, en este caso se imprime if (nodo_actual->izq != null) // si existe, ponemos el hijo izquierdo en la cola cola_enqueue(nodo_actual->izq, &cola_nodos); if (nodo_actual->der != null) // si existe, ponemos el hijo derecho en la cola cola_enqueue(nodo_actual->der, &cola_nodos); } // al vaciarse la cola se han visitado todos los nodos del árbol } Métodos para almacenar árboles binarios Los árboles binarios pueden ser construidos a partir de lenguajes de programación de varias formas. En un lenguaje con registros y referencias, los árboles binarios son construidos típicamente con una estructura de nodos y punteros en la cual se almacenan datos, cada uno de estos nodos tiene una referencia o puntero a un nodo izquierdo y a un nodo derecho denominados hijos. En ocasiones, también contiene un puntero a un único nodo. Si un nodo tiene menos de dos hijos, algunos de los punteros de los hijos pueden ser definidos como nulos para indicar que no dispone de dicho nodo. En la figura adjunta se puede observar la estructura de dicha implementación.
  • 10. Los árboles binarios también pueden ser almacenados como una estructura de datos implícita en vectores, y si el árbol es un árbol binario completo, este método no desaprovecha el espacio en memoria. Tomaremos como notación la siguiente: si un nodo tiene un índice i, sus hijos se encuentran en índices 2i + 1 y 2i + 2, mientras que sus padres (si los tiene) se encuentra en el índice (partiendo de que la raíz tenga índice cero). Este método tiene como ventajas el tener almacenados los datos de forma más compacta y por tener una forma más rápida y eficiente de localizar los datos en particular durante un preoden transversal. Sin embargo, desperdicia mucho espacio en memoria. Codificación de árboles n-arios como árboles binarios Hay un mapeo uno a uno entre los árboles generales y árboles binarios, el cual en particular es usado en Lisp para representar árboles generales como árboles binarios. Cada nodo N ordenado en el árbol corresponde a un nodo N' en el árbol binario; el hijo de la izquierda de N’ es el nodo correspondiente al primer hijo de N, y el hijo derecho de N' es el nodo correspondiente al siguiente hermano de N, es decir, el próximo nodo en orden entre los hijos de los padres de N. Esta representación como árbol binario de un árbol general, se conoce a veces como un árbol binario primer hijo hermano, o un árbol doblemente encadenado. Una manera de pensar acerca de esto es que los hijos de cada nodo estén en una lista enlazada, encadenados junto con el campo derecho, y el nodo sólo tiene un puntero al comienzo o la cabeza de esta lista, a través de su campo izquierdo. Por ejemplo, en el árbol de la izquierda, la A tiene 6 hijos (B, C, D, E, F, G). Puede ser convertido en el árbol binario de la derecha. Un ejemplo de transformar el árbol n-ario a un árbol binario cómo pasar de árboles n-arios a árboles FLOFO.
  • 11. El árbol binario puede ser pensado como el árbol original inclinado hacia los lados, con los bordes negros izquierdos representando el primer hijo y los azules representado los siguientes hermanos. Las hojas del árbol de la izquierda serían escritas en Lisp como: (((N O) I J) C D ((P) (Q)) F (M)) Que se ejecutará en la memoria como el árbol binario de la derecha, sin ningún tipo de letras en aquellos nodos que tienen un hijo izquierdo.  Árboles AVL Árbol avl es un tipo especial de árbol binario ideado por los matemáticos rusos Adelson-Velskii y Landis. Fue el primer árbol de búsqueda binario auto- balanceable que se ideó. Descripción
  • 12. Un ejemplo de árbol binario no equilibrado(no es AVL) Un ejemplo de árbol binario equilibrado (si es AVL) El árbol AVL toma su nombre de las iniciales de los apellidos de sus inventores, Adelson-Velskii y Landis. Lo dieron a conocer en la publicación de un artículo en 1962: "Analgorithmfortheorganization of information" ("Un algoritmo para la organización de la información"). Los árboles AVL están siempre equilibrados de tal modo que para todos los nodos, la altura de la rama izquierda no difiere en más de una unidad de la altura de la rama derecha o viceversa. Gracias a esta forma de equilibrio (o balanceo), la complejidad de una búsqueda en uno de estos árboles se mantiene siempre en orden de complejidad O(log n). El factor de equilibrio puede ser almacenado directamente en cada nodo o ser computado a partir de las alturas de los subárboles. Para conseguir esta propiedad de equilibrio, la inserción y el borrado de los nodos se ha de realizar de una forma especial. Si al realizar una operación de inserción o borrado se rompe la condición de equilibrio, hay que realizar una serie de rotaciones de los nodos. Los árboles AVL más profundos son los árboles de Fibonacci. [Definición formal [editar]Definición de la altura de un árbol Sea un árbol binario de búsqueda y sean y sus subárboles, su altura , es:  si el árbol contiene solo la raíz  si contiene más nodos
  • 13. [editar]Definición de árbol AVL  Un árbol vacío es un árbol AVL  Si es un árbol no vacío y y sus subárboles, entonces es AVL si y solo si:  es AVL  es AVL  [editar]Factor de equilibrio Cada nodo, además de la información que se pretende almacenar, debe tener los dos punteros a los árboles derecho e izquierdo, igual que los árboles binarios de búsqueda (ABB), y además el dato que controla el factor de equilibrio. El factor de equilibrio es la diferencia entre las alturas del árbol derecho y el izquierdo: FE = altura subárbol derecho - altura subárbol izquierdo; Por definición, para un árbol AVL, este valor debe ser -1, 0 ó 1. Si el factor de equilibrio de un nodo es: 0 -> el nodo está equilibrado y sus subárboles tienen exactamente la misma altura. 1 -> el nodo está desequilibrado y su subárbol derecho es un nivel más alto. -1 -> el nodo está desequilibrado y su subárbol izquierdo es un nivel más alto. Si el factor de equilibrio es necesario reequilibrar. [editar]Operaciones Las operaciones básicas de un árbol AVL implican generalmente el realizar los mismos algoritmos que serían realizados en un árbol binario de búsqueda desequilibrado, pero precedido o seguido por una o más de las llamadas "rotaciones AVL".
  • 14. Rotaciones Las rotaciones internas en árboles binarios son operaciones internas comunes utilizadas para mantener el balance perfecto (o casi perfecto del árbol binario. Un árbol balanceado permite operaciones en tiempo logarítmico El reequilibrado se produce de abajo hacia arriba sobre los nodos en los que se produce el desequilibrio. Pueden darse dos casos: rotación simple o rotación doble; a su vez ambos casos pueden ser hacia la derecha o hacia la izquierda. ROTACIÓN SIMPLE A LA DERECHA. De un árbol de raíz (r) y de hijos izquierdo (i) y derecho (d), lo que haremos será formar un nuevo árbol cuya raíz sea la raíz del hijo izquierdo, como hijo izquierdo colocamos el hijo izquierdo de i (nuestro i’) y como hijo derecho construimos un nuevo árbol que tendrá como raíz, la raíz del árbol (r), el hijo derecho de i (d’) será el hijo izquierdo y el hijo derecho será el hijo derecho del árbol (d). oprotDer: AVL{X} -> [AVL{X}] . eqrotDer(arbolBin(R1, arbolBin(R2, I2, D2), D1)) ==
  • 15. arbolBin(R2, I2, arbolBin(R1, D2, D)) . ROTACIÓN SIMPLE A LA IZQUIERDA. De un árbol de raíz (r) y de hijos izquierdo (i) y derecho (d), consiste en formar un nuevo árbol cuya raíz sea la raíz del hijo derecho, como hijo derecho colocamos el hijo derecho de d (nuestro d’) y como hijo izquierdo construimos un nuevo árbol que tendrá como raíz la raíz del árbol (r), el hijo izquierdo de d será el hijo derecho (i’) y el hijo izquierdo será el hijo izquierdo del árbol (i). Precondición : Tiene que tener hijo derecho no vacío. oprotIzq: AVL{X} -> [AVL{X}] . eqrotIzq(arbolBin(R1, I, arbolBin(R2, I2, D2))) == arbolBin(R2, arbolBin(R1, I, I2), D2) . Si la inserción se produce en el hijo derecho del hijo izquierdo del nodo desequilibrado (o viceversa) hay que realizar una doble rotación.
  • 16. ROTACIÓN DOBLE A LA DERECHA. La Rotación doble a la Derecha son dos rotaciones simples, primero rotacion simple izquierda y luego rotación simple derecha. ROTACIÓN DOBLE A LA IZQUIERDA. La Rotación doble a la Izquierda son dos rotaciones simples, primero rotacion simple derecha y luego rotación simple izquierda.
  • 17. Inserción La inserción en un árbol de AVL puede ser realizada insertando el valor dado en el árbol como si fuera un árbol de búsqueda binario desequilibrado y después retrocediendo hacia la raíz, rotando sobre cualquier nodo que pueda haberse desequilibrado durante la inserción. Proceso de inserción: 1.buscar hasta encontrar la posición de inserción o modificación (proceso idéntico a inserción en árbol binario de búsqueda) 2.insertar el nuevo nodo con factor de equilibrio “equilibrado” 3.desandar el camino de búsqueda, verificando el equilibrio de los nodos, y re- equilibrando si es necesario
  • 18. Debido a que las rotaciones son una operación que tienen complejidad constante y a que la altura esta limitada a O (log(n)), el tiempo de ejecución para la inserción es del orden O (log(n)).
  • 19. opinsertar: X$Elt AVL{X} -> AVLNV{X} . eq insertar(R, crear) == arbolBin(R, crear, crear) . ceqinsertar(R1, arbolBin(R2, I, D)) == if (R1==R2) then arbolBin(R2, I, D) elseif (R1<R2) then if ( (altura(insertar(R1,I)) – altura(D)) < 2) then arbolBin(R2, insertar(R1, I), D) else ***hay que reequilibrar if (R1 <raiz(I)) then rotarDer(arbolBin(R2, insertar(R1, I), D)) else rotarDer(arbolBin(R2, rotarIzq(insertar(R1, I)), D)) fi . fi . else if ( (altura(insertar(R1,I)) – altura(D)) < 2) then arbolBin(R2, insertar(R1, I), D) else *** hay que reequilibrar if (R1 >raiz(D)) then rotarIzq(arbolBin(R, I, insertar(R1, D))) else rotatIzq(arbolBin(R, I, rotarDer(insertar(R1, D)))) fi . fi .
  • 20. fi . Extracción El procedimiento de borrado es el mismo que en el caso de árbol binario de búsqueda.La diferencia se encuentra en el proceso de reequilibrado posterior. El problema de la extracción puede resolverse en O (log n) pasos. Una extracción trae consigo una disminución de la altura de la rama donde se extrajo y tendrá como efecto un cambio en el factor de equilibrio del nodo padre de la rama en cuestión, pudiendo necesitarse una rotación. Esta disminución de la altura y la corrección de los factores de equilibrio con sus posibles rotaciones asociadas pueden propagarse hasta la raíz. Borrar A, y la nueva raíz será M. Borrado A, la nueva raíz es M. Aplicamos la rotación a la derecha.
  • 21. El árbol resultante ha perdido altura. En borrado pueden ser necesarias varias operaciones de restauración del equilibrio, y hay que seguir comprobando hasta llegar a la raíz. opeliminar: X$Elt AVL{X} -> AVL{X} . eq eliminar(R, crear) == crear . ceqeliminar(R1, arbolBin(R2, I, D)) == if (R1 == R2) then ifesVacio(I) then D elseifesVacio(D) then I else if (altura(I) - altura(eliminar(min(D),D)) < 2) then arbolBin(min(D), I, eliminar(min(D), D)) ***tenemos que reequilibrar elseif (altura(hijoIzq(I) >= altura(hijoDer(I)))) then rotDer(arbolBin(min(D), I, eliminar(min(D),D))) else rotDer(arbolBin(min(D), rotIzq(I), eliminar(min(D),D)))
  • 22. Búsqueda Ejemplo de TAD AVL en C #include <stdio.h> typedefstruct AVL{ int dato, FB; // FB es la altura del subarbol izquierdo menos la altura del subarbol derecho AVL *izq, *der; bool borrado; } AVL; voidrotarLL(AVL* &A){ //precond: el arbol necesita una rotacion LL AVL* aux = A->izq->der; A->izq->der = A; A->izq->FB = 0; AVL* aux2 = A->izq; A->izq = aux; A->FB = 0; A = aux2; } voidrotarRR(AVL* &A){ //precond: el arbol necesita una rotacion RR AVL* aux = A->der->izq; A->der->izq = A; A->der->FB = 0;
  • 23. AVL* aux2 = A->der; A->der = aux; A->FB = 0; A = aux2; } voidrotarLRalter(AVL* &A){ //precond: el arbol necesita una rotacion LR rotarRR(A->izq); rotarLL(A); } voidrotarRLalter(AVL* &A){ //precond: el arbol necesita una rotacion RL rotarLL(A->der); rotarRR(A); } AVL* Crear(){ return NULL; } void Insert(int n, bool&aumento, AVL* &A){ if (A == NULL){ A = new AVL; A->dato = n; A->FB = 0;
  • 24. A->izq = NULL; A->der = NULL; aumento = true; A->borrado = false; }else{ if (n < A->dato){ Insert(n, aumento, A->izq); if (aumento){ switch (A->FB){ case -1:{ A->FB = 0; aumento = false; break; } case 0:{ A->FB = 1; aumento = true; break; } case 1:{ if (A->izq->FB == 1){ // Si es 1 necesita una rotacion LL si es -1 necesita una rotacion LR rotarLL(A); }else{ rotarLRalter(A);
  • 25. } aumento = false; break; } } } }else{ Insert(n, aumento, A->der); if (aumento){ switch (A->FB){ case -1:{ if (A->der->FB == 1){ // Si es 1 necesita una rotacion RL si es -1 necesita una rotacion RR rotarRLalter(A); }else{ rotarRR(A); } aumento = false; break; } case 0:{ A->FB = -1; aumento = true; break; }
  • 26. case 1:{ A->FB = 0; aumento = false; break; } } } } } } void Insertar(AVL* &A, int n){ bool aumento; Insert(n, aumento, A); } boolEsVacio(AVL* A){ return A == NULL; } bool Pertenece(AVL* A, int n){ if (A == NULL){ returnfalse; }else{ if (A->dato == n){
  • 27. if (A->borrado){ returnfalse; }else{ returntrue; } }else if (n < A->dato){ return Pertenece(A->izq, n); }else{ return Pertenece(A->der, n); } } } void Borrar(AVL* &A, int n){ if (A->dato == n){ A->borrado = true; }else if (n < A->dato){ Borrar(A->izq, n); }else{ Borrar(A->der, n); } }  Árboles Rojo-Negro  Árbol AA
  • 28. Árboles Multicamino  Árboles B (Arboles de búsqueda multicaminoautobalanceados)  Árbol-B+  Árbol-B* Árbol (teoría de grafos) Para otros usos de este término, véase Árbol (desambiguación). En teoría de grafos, un árbol es un grafo en el que cualesquiera dos vértices están conectados por exactamente un camino. Un bosque es una unión disjunta de árboles. Un árbol a veces recibe el nombre de árbol libre. [editar]Definiciones Un árbol es un grafo simple unidireccional G que satisface alguna de las siguientes condiciones equivalentes:  G es conexo y no tiene ciclos .  G no tiene ciclos y, si se añade alguna arista se forma un ciclo.  G es conexo y si se le quita alguna arista deja de ser conexo.  G es conexo y el grafo completo de 3 vértices no es un menor de G.  Dos vértices cualquiera de G están conectados por un único camino simple. Si G tiene muchos vértices, n, entonces las definiciones anteriores son también equivalentes a cualquiera de las siguientes condiciones:  G es conexo y tiene n − 1 aristas.  G es conexo y sin ciclos .  Cualesquiera 2 vértices están unidos por una única trayectoria. un grafo unidireccional simple G es un bosque si no tiene ciclos simples. Un árbol dirigido es un grafo dirigido que sería un árbol si no se consideraran las direcciones de las aristas. Algunos autores restringen la frase al caso en el que todos las aristas se dirigen a un vértice particular, o todas sus direcciones parten de un vértice particular.
  • 29. Un árbol recibe el nombre de árbol con raíz si cada vértice ha sido designado raíz, en cuyo caso las aristas tienen una orientación natural hacia odesde la raíz. Los árboles con raíz, a menudo con estructuras adicionales como orden de los vecinos de cada vértice, son una estructura clave en informática; véase árbol (programación). Un árbol etiquetado es un árbol en el que cada vértice tiene una única etiqueta. Los vértices de un árbol etiquetado de n vértices reciben normalmente las etiquetas {1,2, ..., n}. Un árbol regular u homogéneo es un árbol en el que cada vértice tiene el mismo grado. [editar]Propiedades Todo árbol es a su vez un grafo bipartito. Todo árbol con sólo un conjunto numerable de vértices es además un grafo plano. Todo grafo conexo G admite un árbol de expansión, que es un árbol que contiene cada vértice de G y cuyas aristas son aristas de G. Dado n vértices etiquetados, hay n n−2 maneras diferentes de conectarlos para construir un grafo. El resultado se llama fórmula de Cayley. El número de árboles con n vértices de gradod1,d2,...,dn es: que es un coeficiente multinomial. Contar el número de árboles no etiquetados es un problema complicado. De hecho, no se conoce ninguna fórmula para el número de árboles t(n) con n vértices (debe entederse aquí el número de árboles diferentes salvo isomorfismo de grafos). Los primeros valores de t(n) son 1, 1, 1, 1, 2, 3, 6, 11, 23, 47, 106, 235, 551, 1301, 3159, ... (sucesión A000055 en OEIS). Otter (1948) probó que Una fórmula más exacta para el comportamiento asintótico de t(n) implica que hay dos números α y β (α ≈ 3 y β ≈ 0.5) tales que: