You are on page 1of 51

Sesin UNIVERSIDAD CATLICA DE SANTA MARIA P. P.

INGENIERA SISTEMAS LABORATORIO DE ALGORITMIA Y ESTRUCTURA DE DATOS II AVL: RBOL BINARIO ORDENADO Y BALANCEADO I OBJETIVOS Explicar el TAD rbol Binario AVL. Implementar el TAD rbol Binario. Implementar el TAD rbol Binario AVL. Utilizar los TADs rbol Binario y rbol Binario AVL para la resolucin de problemas. II TEMAS TAD rbol Binario. TAD rbol Binario AVL. III MARCO TERICO DEFINICIN DE RBOL AVL Un rbol se dice balanceado en altura si las alturas de los subrboles izquierdo y derecho de cada nodo difieren en a lo sumo una unidad. Los rboles balanceados en altura se llaman rboles AVL (Por sus creadores Adelson-Velskii & Landis) Para Optimizar las Bsquedas, se intentar mantener los rboles Binarios Ordenados IZQ<RAIZ<DER y Balanceados. Llamados rboles AVL (AdelsonVelskiiLandis) Lo s rboles AVL caracterizan porque la Altura = ASD ASI: 1<=Altura<=1 Restringe la altura de cada uno de los Subrboles Se necesita un campo FDB (Factor de Balanceo) en cada nodo. RBOL AVL: FACTOR DE BALANCEO -

FDB = ASD ASI. FDB: Factor de Equilibrio. ASD: Altura del Subrbol Derecho. ASI: Altura del Subrbol Izquierdo.

Mgter. Juan Pablo Apaza Condori

RBOL AVL: EJEMPLOS DE FACTOR DE EQUILIBRIO FACTOR

Desequilibrio hacia la derecha

EJEMPLO

Equilibrado

Equilibrado

-1

Equilibrado

-2

Desequilibrio 2 hacia la izquierda

Mgter. Juan Pablo Apaza Condori

RBOLAVL: INSERCIN La Insercin se hace siguiendo el camino de bsqueda Puede aumentar la altura de una rama, de manera que cambie el factor de balanceo de dicho nodo. Implica que se retornar por el camino de bsqueda para actualizar el FDB de c/nodo Se puede llegar a Desbalancear (Altura=2) => ReBalanceo. O Puede mejorar: Si al rbol X se le Inserta el 1, resultar en Perfectamente Balanceado. El Proceso termina cuando se llega a la Raz o cuando termina el Rebalanceo del mismo. EJEMPLO DE RBOL AVL El rbol AVL esta Balanceado?

ASI
2

ASD
2

10
0

2
1

18
0

6
0

15
RBOL X 0

20
0

Mgter. Juan Pablo Apaza Condori

EJEMPLO DE RBOL AVL El rbol AVL esta Balanceado?

ASI
3

ASD 10
-1
3

2
2

18
0

6
-1

15
0

20
0

3
0 RBOL X + NODO 3

PROPUESTOS Seale de los siguientes rboles cul/es es/son AVL e indique el FDB de cada nodo.

Mgter. Juan Pablo Apaza Condori

RBOLAVL: REESTRUCTURACIN Hay 4 casos posibles a tener en cuenta, segn donde se hizo la Insercin. 1. Insercin en el Subrbol IZQ De la Rama IZQ de 8

8 4 2
2. Insercin en el Subrbol DER De la Rama DER de 8

14 22

3. Insercin en el Subrbol DER De la Rama IZQ de 8

Mgter. Juan Pablo Apaza Condori

4. Insercin en el Subrbol DER De la Rama IZQ de 8

14

22
SOLUCIN: La ROTACION le devuelve el equilibrio al rbol. Rotacin Simple: Caso 1 y 2: Implica a 8 y su descendiente Rotacin Doble: Caso 3 y 4: Implica a los 3 nodos Soluciones simtricas: En c/caso, las ramas estn opuestas.

Mgter. Juan Pablo Apaza Condori

RBOLAVL: ROTACIN SIMPLE Luego de Insertar el Nodo A el rbol qued desbalanceado. Segn que rama ha crecido, la Rotacin Simple puede ser de izquierdaizquierda (II) o derechaderecha(DD). A LA IZQUIERDA (RSI)

Mgter. Juan Pablo Apaza Condori

A LA IZQUIERDA (RSI): MOVIMIENTOS DE PUNTEROS.

n es puntero al nodo problema.


DER. n1 apunta a rama DER n->der=n1>izq n1->izq=n n=n1

n 8 2
2

n1 n1 14
1

n 14

8
0

20
0

12

20
0

12

rboles opcionales, pueden o no existir

template<class DATO> void ArbolAVL<DATO>::RSI(nodo<DATO>* nod)


{ nodo<DATO> *Padre = nod->padre; nodo<DATO> *P = nod; nodo<DATO> *Q = P->derecho; nodo<DATO> *B = Q->izquierdo; if(Padre) if(Padre->izquierdo == P) Padre->izquierdo = Q; else Padre->derecho = Q; else raiz=Q; // Reconstruir rbol: P->derecho = B; Q->izquierdo = P; // Reasignar padres: P->padre = Q; if(B) B->padre = P; Q->padre = Padre; // Ajustar valores de FE: P->FE = 0; Q->FE = 0; }

Mgter. Juan Pablo Apaza Condori

A LA DERECHA (RSD)

Mgter. Juan Pablo Apaza Condori

A LA DERECHA (RSD): MOVIMIENTOS DE PUNTEROS.

n es puntero al nodo problema.

IZQ (nuestro ej). n1 apunta a rama IZQ n->izq=n1>der n1->der=n n=n1

n n1 4
-1

n1 4 12 1
0 0

8
-2

8
0

1
0

12

rboles opcionales, pueden o no existir

template<class DATO> void ArbolAVL<DATO>::RSD(nodo<DATO>* nod)


{ nodo<DATO> *Padre = nod->padre; nodo<DATO> *P = nod; nodo<DATO> *Q = P->izquierdo; nodo<DATO> *B = Q->derecho; if(Padre) if(Padre->derecho == P) Padre->derecho = Q; else Padre->izquierdo = Q; else raiz=Q; // Reconstruir rbol: P->izquierdo = B; Q->derecho = P; // Reasignar padres: P->padre = Q; if(B) B->padre = P; Q->padre = Padre; // Ajustar valores de FE: P->FE = 0; Q->FE = 0; }

Mgter. Juan Pablo Apaza Condori

10

RBOLAVL: EJEMPLO DE ROTACIN SIMPLE A LA IZQUIERDA Inserte en un rbol AVL la siguiente secuencia:

1, 2, 3, 4, 5, 6, 7, 8, 9
1 Insertando 1, 2, 3, 4, 5

2 Insertando 6

3 Insertando 7

Mgter. Juan Pablo Apaza Condori

11

4 Insertando 8, 9

Mgter. Juan Pablo Apaza Condori

12

RBOLAVL: EJEMPLO DE ROTACIN SIMPLE A LA DERECHA Inserte en un rbol AVL la siguiente secuencia:

9, 8, 7, 6, 5, 4, 3, 2, 1

1 Insertando 9, 8, 7, 6, 5

2 Insertando 4

3 Insertando 3

Mgter. Juan Pablo Apaza Condori

13

4 Insertando 2, 1

Mgter. Juan Pablo Apaza Condori

14

RBOLAVL: ROTACIN DOBLE A LA IZQUIERDA (RDI)

Mgter. Juan Pablo Apaza Condori

15

A LA IZQUIERDA (RDI): MOVIMIENTOS DE PUNTEROS.

n apunta al nodo problema; n1 al hijo de n con problemas, n2 al hijo de n1 DI. Derechaizquierda n1->izq=n2>der n2>der=n1 n->der=n2>izq n2>izq=n n=n2 n 8 5
2

n n1 14
-1

n2 n1 14
0

10 8
0 0

n2 10
0

20

12

20

12

rboles opcionales, pueden o no existir

Mgter. Juan Pablo Apaza Condori

16

template<class DATO> // Rotacin doble a izquierdas void ArbolAVL<DATO>::RDI(nodo<DATO>* nod)


{ nodo<DATO> *Padre = nod->padre; nodo<DATO> *P = nod; nodo<DATO> *Q = P->derecho; nodo<DATO> *R = Q->izquierdo; nodo<DATO> *B = R->derecho; nodo<DATO> *C = R->izquierdo; if(Padre) if(Padre->izquierdo == nod) Padre->izquierdo = R; else Padre->derecho = R; else raiz = R; // Reconstruir rbol: Q->izquierdo = B; P->derecho = C; R->derecho = Q; R->izquierdo = P; // Reasignar padres: R->padre = Padre; P->padre = Q->padre = R; if(B) B->padre = Q; if(C) C->padre = P; // Ajustar valores de FE: switch(R->FE) { case -1: Q->FE = 0; P->FE = 1; break; case 0: Q->FE = 0; P->FE = 0; break; case 1: Q->FE = -1; P->FE = 0; break; } R->FE = 0; }

Mgter. Juan Pablo Apaza Condori

17

A LA DERECHA (RDD)

Mgter. Juan Pablo Apaza Condori

18

A LA DERECHA (RDD): MOVIMIENTOS DE PUNTEROS.

n apunta al nodo problema; n1 al hijo de n con problemas, n2 al hijo de n1 ID: izquierdaderecha n1->der=n2>izq n2>izq=n1 n->izq=n2>der n2>der=n n=n2 n 8
-2

n 6 10 4
0 0

n2 n1 8
0

n1 4
1

n2 6
0

10

rboles opcionales, pueden o no existir

Mgter. Juan Pablo Apaza Condori

19

template<class DATO> void ArbolAVL<DATO>::RDD(nodo<DATO>* nod)


{ nodo<DATO>*Padre = nod->padre; nodo<DATO>*P = nod; nodo<DATO> *Q = P->izquierdo; nodo<DATO> *R = Q->derecho; nodo<DATO> *B = R->izquierdo; nodo<DATO> *C = R->derecho; if(Padre) if(Padre->derecho == nod) Padre->derecho = R; else Padre->izquierdo = R; else raiz = R; // Reconstruir rbol: Q->derecho = B; P->izquierdo = C; R->izquierdo = Q; R->derecho = P; // Reasignar padres: R->padre = Padre; P->padre = Q->padre = R; if(B) B->padre = Q; if(C) C->padre = P; // Ajustar valores de FE: switch(R->FE) { case -1: Q->FE = 0; P->FE = 1; break; case 0: Q->FE = 0; P->FE = 0; break; case 1: Q->FE = -1; P->FE = 0; break; } R->FE = 0; }

Mgter. Juan Pablo Apaza Condori

20

RBOLAVL: EJEMPLO DE ROTACIN DOBLES A LA IZQUIERDA Inserte en un rbol AVL la siguiente secuencia:

1, 3, 2, 8, 5, 4, 10, 9, 7, 6
1 Insertando 1, 3, 2, 8, 5

2 Insertando 4, 10, 9

Mgter. Juan Pablo Apaza Condori

21

3 Insertando 7, 6

Mgter. Juan Pablo Apaza Condori

22

RBOLAVL: EJEMPLO DE ROTACIN DOBLES A LA DERECHA Inserte en un rbol AVL la siguiente secuencia:

10, 8, 9, 3, 6, 7, 1, 2, 4, 5
1 Insertando 10, 8, 9, 3, 6

2 Insertando 7, 1, 2

Mgter. Juan Pablo Apaza Condori

23

3 Insertando 4, 5

Mgter. Juan Pablo Apaza Condori

24

RBOLAVL: QU ROTACIN APLICAR ? Si un rbol est desbalanceado hacia la izquierda (-2), aplicar rotacin hacia derecha En un rbol que est desbalanceado hacia la izquierda revisar el factor de equilibrio del subrbol izquierdo Si un rbol est desbalanceado hacia la derecha (2), aplicar rotacin hacia izquierda En un rbol que est desbalanceado hacia la derecha revisar el factor de equilibrio del subrbol derecho Si el signo de los factores coincide, se aplica una rotacin

simple

Si el signo de los factores no

coincide, se aplica una rotacin doble

Mgter. Juan Pablo Apaza Condori

25

RBOLAVL: EQUILIBRAR

template<class DATO> void ArbolAVL<DATO>::Equilibrar(nodo<DATO>*nod,char lado,int oper)


{ while(nod) { if(oper==1) { if(lado=='D') nod->FE++; else nod->FE--; } else { if(lado=='D') nod->FE--; else nod->FE++; } if(nod->FE==0)break; if(nod->FE==2 && nod->derecho->FE==1){RSI(nod);break;} if(nod->FE==2 && nod->derecho->FE==-1){RDI(nod);break;} if(nod->FE==-2 && nod->izquierdo->FE ==-1){RSD(nod);break;} if(nod->FE==-2 && nod->izquierdo->FE ==1){RDD(nod);break;} if(nod->padre) { if(nod->padre->derecho==nod) lado='D'; else lado='I'; } nod=nod->padre; } }

Mgter. Juan Pablo Apaza Condori

26

RBOLAVL: INSERTAR template<class DATO> void ArbolAVL<DATO>::insertar( DATO dat) { if(!Buscar(dat)) { nodo<DATO>* padre=NULL; actual = raiz; while(!Vacio(actual) && dat != actual->dato) { padre=actual; if(dat>actual->dato) actual=actual->derecho; else if(dat<actual->dato) actual=actual->izquierdo; } if(!Vacio(actual)) return;

if(Vacio(padre))

raiz=new nodo<DATO>(dat); else

if(dat<padre->dato)

{ padre->izquierdo=new nodo<DATO>(dat,padre);

} else

Equilibrar(padre,'I',1); if(dat>padre->dato)
{

padre->derecho=new nodo<DATO>(dat,padre); } n++;

Equilibrar(padre,'D',1);

} else { cout<<"EL ELEMENTO YA SE ENCUENTRA..."<<endl; getch(); } } PROPUESTOS 1 Dada la secuencia de claves enteras:210,31,69,85,51,36,97,25,50, Representar grficamente el rbol AVL correspondiente 2 Dada la secuencia de claves enteras:1,2,3,4,5,6,7,8, 9,10,11,12,13. Representar grficamente el rbol AVL correspondiente

13,1,23,28,10.

Mgter. Juan Pablo Apaza Condori

27

RBOLAVL: ELIMINACIN 1. Borrar el nodo como en un ABB clsico Presenta 2 casos bien diferenciados Si se trata de una hoja se elimina directamente Si tiene un nico hijo se elimina el nodo haciendo que su nodo padre pase a referenciar a su nodo hijo Si tiene dos hijos : Se sustituye el nodo por el menor elemento de su Subrbol Derecho Se elimina el nodo correspondiente a dicho menor elemento. Se sustituye el nodo con el mayor de las Claves Menores del Subrbol Izquierdo. Bajaremos al 1er nodo de la Rama Izquierda Como la clave mayor est a la derecha, se contina bajando a derecha hasta encontrar un nodo hoja (El Mayor de los Menores que reemplazar el dato a eliminar). El planteamiento ms simple en este caso es reemplazar el nodo que queremos borrar con su predecesor en el recorrido inorden. Esta estrategia garantiza que se mantiene la propiedad de los rboles binarios de bsqueda. El problema se convierte entonces en el de eliminar el nodo que ha quedado libre el predecesor en inorden. 2. Recalcular los factores de balanceo que cambiaron por el borrado, se recorre el camino desde el padre del nodo eliminado de regreso hacia la raz, actualizando los equilibrios por el camino. 3. Para cada nodo con factor de balanceo RBOLAVL: EJEMPLO DE ELIINACIN Borrar el nodo con valor 5

2 hay que hacer una rotacin simple o doble

n 84 10 5
2

86 86
1 RSI 0

85

90
1

84
0

90
0

99

10

85

99

Mgter. Juan Pablo Apaza Condori

28

Borrar el nodo con valor 6

n 13
2

36 40
-1

3 1 6 12 36
-1

13
RDI 0

40
0

45 38 75 1

3 12 15

34

38

45 75

34 15

PROPUESTOS Hallar el rbol resultante luego de realizar la operacin de eliminar

n 13 3 1 6 12 36 38 40 45 75

34 15

Mgter. Juan Pablo Apaza Condori

29

n 13 3 1 6 12 36 38 40 45 75

34 15 n 13 3

40 12 45 38 75

1 6

36

34 15

Mgter. Juan Pablo Apaza Condori

30

RBOLAVL: PROGRAMA EN C++

NODOS.H
#ifndef NODOS_H #define NODOS_H template <class DATO> class ArbolAVL; template<class DATO>class nodo { public: nodo(const DATO dat,nodo<DATO>*pad=0,nodo<DATO> *izq=0,nodo<DATO>*der=0) { dato=dat; izquierdo=izq; derecho=der; padre=pad; FE=0; }

DATO dato;
int FE;

friend class ArbolAVL<DATO>; }; //typedef nodo *pnodo; #endif

nodo<DATO> *izquierdo; nodo<DATO> *derecho; nodo<DATO> *padre;

ARBOL.H
#ifndef ARBOL_h #define ARBOL_h #include "nodos.h" #include <iostream.h> #include <stdio.h> #include <stdlib.h> #include <iomanip.h> #include <conio.h> #include <iomanip.h> int n=0,h1,h2; template <class DATO> class ArbolAVL { public: ArbolAVL() { raiz=NULL;actual=NULL; } ~ArbolAVL() { Podar(raiz); }
Mgter. Juan Pablo Apaza Condori

31

void ramaizq(nodo <DATO>*); void ramader(nodo <DATO>*); void altura(); void numnodos(); void mostr(); void most(nodo<DATO>*,int); void insertar( DATO ); void Borrar(); void Borrar2(DATO); void eng(); void rainor(); void rapost(); void rapreo(); bool Buscar( DATO ); void parentesco(); bool Vacio(nodo<DATO>*r) { return r==NULL; } bool EsHoja (nodo<DATO>*r) { return !r->derecho && !r->izquierdo; } // void InOrden(void (*func)(DATO&,int), nodo<DATO>*nodo=NULL,bool r=true); void InOrden(nodo<DATO>*); // void PreOrden(void (*func)(DATO&,int), nodo<DATO>*nodo=NULL,bool r=true); void PreOrden(nodo<DATO>*); // void PostOrden(void (*func)(DATO&,int),nodo<DATO>*nodo=NULL,bool r=true); void PostOrden(nodo<DATO>*); void Equilibrar(nodo<DATO> *, char, int); nodo<DATO>*nodenc; private:

nodo<DATO>* raiz; nodo<DATO>* actual;

void RSI(nodo<DATO>* nod ); void RSD(nodo<DATO>* nod); void RDI(nodo<DATO>* nod ); void RDD(nodo<DATO>* nod); void Podar(nodo<DATO>* &);

}; template<class DATO> void ArbolAVL<DATO>::insertar( DATO dat) { if(!Buscar(dat)) { nodo<DATO>* padre=NULL; actual = raiz; while(!Vacio(actual) && dat != actual->dato) { padre=actual; if(dat>actual->dato)
Mgter. Juan Pablo Apaza Condori

32

actual=actual->derecho; else if(dat<actual->dato) actual=actual->izquierdo; } if(!Vacio(actual)) return;

if(Vacio(padre))

raiz=new nodo<DATO>(dat); else

if(dat<padre->dato)
{

padre->izquierdo=new nodo<DATO>(dat,padre); } else

Equilibrar(padre,'I',1);

if(dat>padre->dato)
{ padre->derecho=new nodo<DATO>(dat,padre); }

Equilibrar(padre,'D',1);

n++; } else { cout<<"EL ELEMENTO YA SE ENCUENTRA..."<<endl; getch(); } }

template<class DATO> void ArbolAVL<DATO>::Equilibrar(nodo<DATO>*nod,char lado,int oper)


{ while(nod) { if(oper==1) { if(lado=='D') nod->FE++; else nod->FE--; } else { if(lado=='D') nod->FE--; else nod->FE++; } if(nod->FE==0)break; if(nod->FE==2 && nod->derecho->FE==1){RSI(nod);break;} if(nod->FE==2 && nod->derecho->FE==-1){RDI(nod);break;} if(nod->FE==-2 && nod->izquierdo->FE ==-1){RSD(nod);break;} if(nod->FE==-2 && nod->izquierdo->FE ==1){RDD(nod);break;}
Mgter. Juan Pablo Apaza Condori

33

if(nod->padre) { if(nod->padre->derecho==nod) lado='D'; else lado='I'; } nod=nod->padre; } }

template<class DATO> void ArbolAVL<DATO>::RSD(nodo<DATO>* nod)


{ nodo<DATO> *Padre = nod->padre; nodo<DATO> *P = nod; nodo<DATO> *Q = P->izquierdo; nodo<DATO> *B = Q->derecho; if(Padre) if(Padre->derecho == P) Padre->derecho = Q; else Padre->izquierdo = Q; else raiz=Q; // Reconstruir rbol: P->izquierdo = B; Q->derecho = P; // Reasignar padres: P->padre = Q; if(B) B->padre = P; Q->padre = Padre; // Ajustar valores de FE: P->FE = 0; Q->FE = 0; }

template<class DATO> void ArbolAVL<DATO>::RSI(nodo<DATO>* nod)


{ nodo<DATO> *Padre = nod->padre; nodo<DATO> *P = nod; nodo<DATO> *Q = P->derecho; nodo<DATO> *B = Q->izquierdo; if(Padre) if(Padre->izquierdo == P) Padre->izquierdo = Q; else Padre->derecho = Q; else raiz=Q; // Reconstruir rbol: P->derecho = B; Q->izquierdo = P; // Reasignar padres: P->padre = Q; if(B) B->padre = P; Q->padre = Padre; // Ajustar valores de FE: P->FE = 0; Q->FE = 0;

Mgter. Juan Pablo Apaza Condori

34

template<class DATO> // Rotacin doble a derechas void ArbolAVL<DATO>::RDD(nodo<DATO>* nod)


{ nodo<DATO>*Padre = nod->padre; nodo<DATO>*P = nod; nodo<DATO> *Q = P->izquierdo; nodo<DATO> *R = Q->derecho; nodo<DATO> *B = R->izquierdo; nodo<DATO> *C = R->derecho; if(Padre) if(Padre->derecho == nod) Padre->derecho = R; else Padre->izquierdo = R; else raiz = R; // Reconstruir rbol: Q->derecho = B; P->izquierdo = C; R->izquierdo = Q; R->derecho = P; // Reasignar padres: R->padre = Padre; P->padre = Q->padre = R; if(B) B->padre = Q; if(C) C->padre = P; // Ajustar valores de FE: switch(R->FE) { case -1: Q->FE = 0; P->FE = 1; break; case 0: Q->FE = 0; P->FE = 0; break; case 1: Q->FE = -1; P->FE = 0; break; } R->FE = 0; }

template<class DATO> // Rotacin doble a izquierdas void ArbolAVL<DATO>::RDI(nodo<DATO>* nod)


{ nodo<DATO> *Padre = nod->padre; nodo<DATO> *P = nod; nodo<DATO> *Q = P->derecho; nodo<DATO> *R = Q->izquierdo; nodo<DATO> *B = R->derecho; nodo<DATO> *C = R->izquierdo; if(Padre) if(Padre->izquierdo == nod) Padre->izquierdo = R; else Padre->derecho = R; else raiz = R; // Reconstruir rbol: Q->izquierdo = B; P->derecho = C; R->derecho = Q; R->izquierdo = P; // Reasignar padres: R->padre = Padre;
Mgter. Juan Pablo Apaza Condori

35

P->padre = Q->padre = R; if(B) B->padre = Q; if(C) C->padre = P; // Ajustar valores de FE: switch(R->FE) { case -1: Q->FE = 0; P->FE = 1; break; case 0: Q->FE = 0; P->FE = 0; break; case 1: Q->FE = -1; P->FE = 0; break; } R->FE = 0; }

template<class DATO> bool ArbolAVL<DATO>::Buscar(DATO dat)


{ nodo<DATO>* r; r=raiz; int flag=0; while(r) { if(r->dato==dat) { flag=1; nodenc=r; break; } else { if(dat>r->dato) { r=r->derecho; flag=0; } else//menor { r=r->izquierdo; flag=0; } } } if(flag!=1) return false; else return true; }

template<class DATO> void ArbolAVL<DATO>::Podar(nodo<DATO>* &nod)


{ if(nod) { Podar(nod->izquierdo); Podar(nod->derecho); delete nod; nod=NULL; }

Mgter. Juan Pablo Apaza Condori

36

template<class DATO> //void ArbolAVL::InOrden(void (*func)(int&), pnodo nodo,bool r) void ArbolAVL<DATO>::InOrden(nodo<DATO>* r)


{ /* if(r) nodo=raiz; if(nodo->izquierdo) InOrden(func,nodo->izquierdo,false); func(nodo->dato); if(nodo->derecho) InOrden(func,nodo->derecho,false); */ if(r!=NULL) { InOrden(r->izquierdo); printf(" \t%d <%i>",r->dato,r->FE); InOrden(r->derecho); } // getch(); }

template<class DATO> void ArbolAVL<DATO>::rainor()


{ InOrden(raiz); getch(); } //void ArbolAVL::PreOrden(void (*func)(int&),pnodo nodo,bool r)

template<class DATO> void ArbolAVL<DATO>::PreOrden(nodo<DATO>* r)


{ /*if(r) nodo=raiz; func(nodo->dato); if(nodo->izquierdo) PreOrden(func,nodo->izquierdo,false); if(nodo->derecho) PreOrden(func,nodo->derecho,false);*/ if(r!=NULL) { printf(" \t%d <%i>",r->dato,r->FE); PreOrden(r->izquierdo); PreOrden(r->derecho); } // getch(); }

template<class DATO> void ArbolAVL<DATO>::rapreo()


{ PreOrden(raiz); getch(); } //void ArbolAVL::PostOrden(void (*func)(int&),pnodo nodo,bool r)

template<class DATO> void ArbolAVL<DATO>::PostOrden(nodo<DATO>* r)


Mgter. Juan Pablo Apaza Condori

37

{ /*if(r) nodo=raiz; if(nodo->izquierdo) PostOrden(func,nodo->izquierdo,false); if(nodo->derecho) PostOrden(func,nodo->derecho,false); func(nodo->dato);*/ if(r!=NULL) { PostOrden(r->izquierdo); PostOrden(r->derecho); printf(" \t%d <%i>",r->dato,r->FE); } // getch(); }

template<class DATO> void ArbolAVL<DATO>::rapost()


{ PostOrden(raiz); getch(); }

template<class DATO> void ArbolAVL<DATO>::most(nodo<DATO>* r,int n)


{ int x; if(r!=NULL) { n--; most(r->izquierdo,n); for(x=0;x<n;x++) printf(" "); printf("(%d)\n",r->dato); most(r->derecho,n); } }

template<class DATO> void ArbolAVL<DATO>::eng()


{ if(raiz) { system("cls");printf("\n\n");most(raiz,n);} else cout<<"NO HAY NODOS PARA GRAFICAR.."<<endl; getch(); }

template<class DATO> void ArbolAVL<DATO>::numnodos()


{ printf("HAY %d NODOS EN EL ARBOL\n",n); getch(); } /////////////////////////////////////////////////////////////////////////////////////

template<class DATO> void ArbolAVL<DATO>::Borrar()


{ int dat,flag,yes,exito;

Mgter. Juan Pablo Apaza Condori

38

bool detector; nodo<DATO>* r,*aux,*ant,*ant2; system("cls"); if(raiz==NULL) cout<<"NO HAY NINGUN ELEMENTO EN EL ARBOL PARA ELIMINAR"<<endl; else { cout<<"SE VA A ELIMINAR EL NODO QUE CONTENGA EL ITEM QUE INGRESE"<<endl; cout<<"INGRESE ITEM: ";cin>>dat; detector=Buscar(dat); if(!detector) cout<<"NO SE PUEDE ELIMINAR UN ELEMENTO QUE NO ESTA"<<endl; else { if(raiz->dato==dat) { if(raiz->izquierdo==NULL && raiz->derecho==NULL) { aux=raiz; delete aux; raiz=NULL; } else { //ama2=0; if(raiz->izquierdo!=NULL) { r=raiz->izquierdo; exito=0; if(r->derecho==NULL) goto choque; else { while(exito==0) { ant=r; r=r->derecho; if(r->derecho==NULL) { exito=1; ant->derecho=r->derecho; raiz->dato=r->dato; } } } } else { choque: if(raiz->derecho!=NULL) { r=raiz->derecho; exito=0; if(r->izquierdo==NULL) { raiz->dato=r->dato;

Mgter. Juan Pablo Apaza Condori

39

raiz->derecho=r->derecho; aux=r; delete aux; } else { while(exito==0) { ant=r; r=r->izquierdo; if(r->izquierdo==NULL) { exito=1; ant->izquierdo=r->izquierdo; raiz->dato=r->dato; } } } } else { r=raiz->izquierdo; raiz->dato=r->dato; aux = r; raiz->izquierdo=r->izquierdo; delete aux; } } } } else { ///////////////////////////////////////////////// r=raiz; if(r->dato==dat && r->izquierdo ==NULL && r->derecho==NULL) { aux=raiz; delete aux; raiz=NULL; } else { while(r!=NULL) { flag=0; ant=r; if(dat>r->dato) { r=r->derecho; flag=2; } else { r=r->izquierdo; flag=1; }

Mgter. Juan Pablo Apaza Condori

40

///////////dos hijos////////// if(r->dato==dat && r->izquierdo!=NULL && r->derecho!=NULL) { ant2=r; r=r->izquierdo; if(r->derecho==NULL) { ant2->dato=r->dato; if(r->izquierdo==NULL) { ant2->izquierdo=r->derecho; r=NULL; break; } else { ant2->izquierdo=r->izquierdo; aux=r; r=NULL; delete aux; break; } } else { yes=0; while(yes==0) { aux=r; r=r->derecho; if(r->derecho==NULL) { ant2->dato=r->dato; ant2->izquierdo=r->izquierdo; aux->derecho=NULL; delete r->derecho; yes=1; r=NULL; } } } } else { if(r->dato==dat && r->izquierdo==NULL && r->derecho!=NULL) { if(flag==2) { ant->derecho=r->derecho; aux=r; delete aux; r=NULL; break; } }

Mgter. Juan Pablo Apaza Condori

41

if(r->dato==dat && r->izquierdo!=NULL && r->derecho==NULL) { if(flag==2) { ant->derecho=r->izquierdo; aux=r; delete aux; r=NULL; break; } } if(r->dato==dat && r->izquierdo!=NULL && r->derecho==NULL) { if(flag==1) { ant->izquierdo=r->izquierdo; aux=r; delete aux; r=NULL; break; } } if(r->dato==dat && r->izquierdo==NULL && r->derecho!=NULL) { if(flag==1) { ant->izquierdo=r->derecho; aux=r; delete aux; r=NULL; break; } } if(r->dato==dat && r->izquierdo==NULL && r->derecho==NULL) { if(flag==1) { aux=r; ant->izquierdo=NULL; r=NULL; } if(flag==2) { aux=r; ant->derecho=NULL; r=NULL; } delete aux; } } n--; } } }

Mgter. Juan Pablo Apaza Condori

42

cout<<"ELIMINANDO..."<<endl; } } getch(); }

template<class DATO> void ArbolAVL<DATO>::mostr()


{ int op; //ArbolAVL ArbolInt; if(Vacio(raiz)){printf("NO HAY ELEMENTOS EN EL ARBOL\n");getch();return;} system("cls"); cout<<"\t\t******************************"<<endl; cout<<"\t\t\t1.- MODO PREORDEN"<<endl; cout<<"\t\t\t2.- MODO INORDEN"<<endl; cout<<"\t\t\t3.- MODO POSTORDEN"<<endl; cout<<"\t\t******************************"<<endl; cout<<"Opcion: ";cin>>op; printf("\n\n\n\n"); // system("cls"); switch(op) { case 1: rapreo(); break; case 2: rainor(); break; case 3: rapost(); break; } // getch(); }

template<class DATO> void ArbolAVL<DATO>::altura()


{ if(Vacio(raiz)) return; ramaizq(raiz->izquierdo); ramader(raiz->derecho); cout<<h1<<endl; cout<<h2<<endl; // h1++; // h2++; if(h1>h2) printf("LA ALTURA DEL ARBOL ES %d \n",h1); else printf("LA ALTURA DEL ARBOL ES %d \n",h2); getch(); } template<class DATO> void ArbolAVL<DATO>::ramaizq(nodo<DATO>* r) { if(r==NULL) h1=0;

Mgter. Juan Pablo Apaza Condori

43

else { ramaizq(r->izquierdo); ramaizq(r->derecho); h1++; } }

template<class DATO> void ArbolAVL<DATO>::ramader(nodo<DATO>* r)


{ if(r==NULL) h2=0; else { ramader(r->izquierdo); ramader(r->derecho); h2++; } }

template<class DATO> void ArbolAVL<DATO>::Borrar2(DATO elemento)


{ nodo<DATO>* aux; nodo<DATO>*auxiz; nodo<DATO>*auxde; nodo<DATO>*recorre; nodo<DATO>*ese; aux=raiz; if(Vacio(raiz)){ printf("NO HAY ARBOL\n");getch();return;} if(!Buscar(elemento)) { printf("EL ELEMENTO NO SE ENCUENTRA...\n");getch(); return; } else { if(nodenc->dato==raiz->dato) { if(raiz->izquierdo==NULL && raiz->derecho==NULL) { Podar(raiz); n=0; return; } } if(nodenc->izquierdo!=NULL && nodenc->derecho!=NULL) { auxiz=nodenc->izquierdo; if(auxiz->derecho==NULL) { nodenc->dato=auxiz->dato; nodenc->izquierdo=auxiz->izquierdo; delete auxiz; if(raiz->dato==nodenc->dato) Equilibrar(raiz,'I',-1);

Mgter. Juan Pablo Apaza Condori

44

else Equilibrar(nodenc->padre,'I',-1); } else if(auxiz->derecho!=NULL) { recorre=auxiz->derecho; while(recorre) { ese=recorre; recorre=recorre->derecho; } nodenc->dato=ese->dato; auxde=ese->padre; auxde->derecho=recorre; delete ese; if(raiz->dato==nodenc->dato) Equilibrar(raiz,'I',-1); else Equilibrar(nodenc->padre,'I',-1); } } else {///// if(nodenc->izquierdo==NULL && nodenc->derecho==NULL) { aux=nodenc->padre; auxiz=aux->izquierdo; auxde=aux->derecho; if(auxiz) { if(auxiz->dato==nodenc->dato) { aux->izquierdo=nodenc->izquierdo;//puede ser nodenc derecho los dos son nulos Equilibrar(nodenc->padre,'I',-1); } } if(auxde) { if(auxde->dato==nodenc->dato) { aux->derecho=nodenc->derecho; Equilibrar(nodenc->padre,'D',-1); } } delete nodenc; } else { aux=nodenc->padre; if(nodenc->izquierdo==NULL && nodenc->derecho!=NULL) { if(aux->derecho->dato==nodenc->dato) { aux->derecho=nodenc->derecho; Equilibrar(nodenc->padre,'D',-1); }

Mgter. Juan Pablo Apaza Condori

45

else if(aux->izquierdo->dato==nodenc->dato) { aux->izquierdo=nodenc->izquierdo; Equilibrar(nodenc->padre,'I',-1); } } else if(nodenc->derecho==NULL && nodenc->izquierdo!=NULL) { if(aux->izquierdo->dato==nodenc->dato) { aux->izquierdo=nodenc->izquierdo; Equilibrar(nodenc->padre,'I',-1); } else if(aux->derecho->dato==nodenc->dato) { aux->derecho=nodenc->derecho; Equilibrar(nodenc->padre,'D',-1); } } delete nodenc; } } printf("ELIMINANDO...\n");getch(); n--; } }

template<class DATO> void ArbolAVL<DATO>::parentesco()


{ int ele; if(Vacio(raiz)){printf("NO HAY ELEMENTOS...\n");getch();return;} printf("INGRESE EL ELEMENTO: ");cin>>ele; if(Buscar(ele)) { system("cls"); if(ele==raiz->dato) cout<<ele<<" NO TIENE PADRE, ES LA RAIZ.."<<endl; else cout<<"PADRE : "<<nodenc->padre->dato<<endl; if(nodenc->izquierdo) cout<<"H. IZQ : "<<nodenc->izquierdo->dato<<endl; else cout<<"H. IZQ : NO TIENE"<<endl; if(nodenc->derecho) cout<<"H. DER : "<<nodenc->derecho->dato<<endl; else cout<<"H. DER : NO TIENE"<<endl; getch(); } }

#endif

Mgter. Juan Pablo Apaza Condori

46

ARBOLAVL.CPP
#include "ARBOL.h" //#include "nodos.h" #include <iostream.h> #include <conio.h> #include <stdio.h> #include <stdlib.h> #include <iomanip.h>

void mostr();
{

/*template<class DATO>

void Mostrar(int &d)


printf("%d,",d); }*/

void main()
{

int op, ele; char c=1; ArbolAVL<int> ArbolInt; system("cls"); do { ///getch(); system("cls"); cout<<"\n\n\n"<<endl; // cout<<"\t\t\t"<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<< c<<c<<c<<c<<c<<endl; cout<<"\t\t\t1.-\tINSERTAR NODO"<<endl; cout<<"\t\t\t2.-\tBUSCAR"<<endl; cout<<"\t\t\t3.-\tGRAFICAR"<<endl; cout<<"\t\t\t4.-\tELIMINAR"<<endl; cout<<"\t\t\t5.-\tMOSTRAR"<<endl; // cout<<"\t\t\t6.-\tPROFUNDIDAD"<<endl; // cout<<"\t\t\t7.-\t# DE NODOS"<<endl; // cout<<"\t\t\t8.-\tPARENTESCO"<<endl; cout<<"\t\t\t9.-\tSALIR"<<endl; // cout<<"\t\t\t"<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<<c<< c<<c<<c<<c<<c<<endl; //cout<<"\t\t\t***************************\n"; cout<<"\t\t\tOPCION: ";cin>>op; switch(op) { case 1: { printf("ELEMENTO\t: ");cin>>ele; ArbolInt.insertar(ele); break; } case 2: { printf("ELEMENTO\t: ");cin>>ele; if(ArbolInt.Buscar(ele))

Mgter. Juan Pablo Apaza Condori

47

cout<<"EL ELEMENTO SI ESTA..."<<endl; else cout<<"EL ELEMENTO NO ESTA..."<<endl; getch(); break; } case 3: { ArbolInt.eng(); break; } case 4: { //if(ArbolInt.Vacio(aux)) printf("EL ARBOL ESTA VACIO...\n"); //else //{ printf("INGRESE ELEMENTO: "); cin>>ele; ArbolInt.Borrar2(ele); // } //ArbolInt.Borrar(); break; } case 5: ArbolInt.mostr(); break; case 6: ArbolInt.altura(); break; case 7: ArbolInt.numnodos(); break; case 8: ArbolInt.parentesco(); break; case 9: exit(1); break; } }while(op); }

Mgter. Juan Pablo Apaza Condori

48

IV ACTIVIDADES 1 Ingrese a la siguiente direccin URL http://webpages.ull.es/users/jriera/Docencia/AVL/AVL%20tree%20applet.htm

Mgter. Juan Pablo Apaza Condori

49

V EJERCICIOS 1 Determine cual de los siguientes rboles es un rbol AVL e indique el FDB de cada nodo.

D
2 Dado el rbol AVL:

InsertarNodo, si se pretende insertar el valor 2. b) EliminarNodo, si se pretende borrar el valor 17.


a) 3 Agregue los mtodos NumNodosDerecho y NumNodosIzquierdo al rbol AVL, los cuales retornan la cantidad de nodos. 4 Agregue un mtodo que cuente la cantidad de nodos con hijo izquierdo y natidad de nodos con hijo derecho.

Mgter. Juan Pablo Apaza Condori

50

5 Insertar la secuencia

38, 20, 57, 47, 46

en el AVL:

5 Insertar 40,

33, 46, 6, 8, 24, 18, 22, 25, 60 en un AVL vaco

6 Se quiere leer un archivo de texto y almacenar en memoria todas las palabras de dicho texto y su frecuencia. La estructura de datos va ser tal que permita realizar una bsqueda en un tiempo O(log n)), sin que dependa de la entrada de datos, por o que se requiere utilizar un rbol AVL. El archivo de texto se llama carta.dat, se pide almacenar dicho texto en memoria, utilizando la estructura rbol indicada anteriormente. Posteriormente se ha de realizar un procedimiento, que dada una palabra nos indique el nmero de veces que aparece en el texto. 7 En un archivo de texto se encuentra los datos(nombre, apellidos, direccin, telefono) completos de los alumnos del taller de teatro de la universidad. Escribir un programa que lea el archivo y forme un rbol binario equilibrado (AVL) con respecto a la clave apellido .

8 Una empresa de servicios tiene tres departamentos, comercial(1), explotacin(2) y comunicaciones(3). Cada empleado est adscrito a uno de ellos. Se ha realizado una redistribucin de personal entre los departamentos. El archivo EMPRESA contiene en cada registro los campos Numero_Idt, Origen, Destino.
El Origen toma los valores 1, 2, 3 dependiendo del departamento inicial al que pertenece el empleado. El campo Destino toma los mismos valores, dependiendo del nuevo departamento asignado al empleado. El archivo no est ordenado. Escribir un programa que almacene los registros del archivo EMPRESA en tres rboles AVL, uno por cada departamento de origen, y realice el intercambio de registros en los rboles segn el campo destino.

Mgter. Juan Pablo Apaza Condori

51

You might also like