NOMBRE ALUMNO: Apellido paterno Apellido materno Nombre (s) No. BOLETA INSTITUTO POLITÉCNICO NACIONAL SECRETARIA ACADÉMICA DIRECCIÓN DE EDUCACIÓN SUPERIOR ESIME CULHUACAN GRUPO FECHA DIA MES AÑO INGENIERÍA EN COMPUTACIÓN ASIGNATURA ESTRUCTURAS DE DATOS PROFESOR M. en C. BEATRIZ EUGENIA CORONA RAMÍREZ PRÁCTICA No. 14 ÁRBOL BALANCEADO 1. Objetivo El alumno usará la estructura de datos árbol binario, efectuará operaciones fundamentales como creación de un nodo, inserción de un nodo, eliminación de un nodo, balanceo de un árbol, etc. 2. Material y Equipo Computadora, Compilador C y/o Java y unidad de almacenamiento (USB) 3. Introducción teórica Formalmente se define un árbol balanceado como un árbol binario de búsqueda, en el cuál se debe cumplir la siguiente condición: Para todo NODO T del árbol, las altura del los subárboles izquierdo y derecho no deben diferir en más de una unidad. HRI – HRD <= 1 Donde HRI es la altura de la rama o subárbol izquierdo y HRD es la altura de la rama o subárbol derecho. En la siguiente figura se muestran dos ejemplos de árboles balanceados. 35 60 20 40 40 90 25 15 45 75 97 68 167 Inserción en árboles balanceados Al insertar un elemento en un árbol balanceado se deben distinguir los siguientes casos: Las ramas izquierda (RI) y derecha (RD) del árbol tienen la misma altura (HRI = HRD), por lo tanto: Si se inserta un elemento en RI, entonces HRI será mayor en una unidad a HRD. Si se inserta un elemento en RD, entonces HRD será mayor en una unidad a HRI. Observe que en cualquiera de los casos mencionados anteriormente no se viola el criterio de equilibrio del árbol. Las ramas izquierda (RI) y derecha (RD) del árbol tienen altura diferente (HRI HRD): Supongamos que HRI < HRD : Si se inserta un elemento en RI, entonces HRI será igual a HRD (Las ramas quedan de la misma altura por lo que se mejoro el equilibrio del árbol). Si se inserta un elemento en RD, entonces se rompe el criterio de equilibrio del árbol y es necesario reestructurarlo. Supongamos que HRI > HRD : Si se inserta un elemento en RI, entonces se rompe el criterio de equilibrio del árbol y es necesario reestructurarlo. Si se inserta un elemento en RD, entonces HRD será igual a HRI (Las ramas quedan de la misma altura por lo que se mejoro el equilibrio del árbol). En la siguiente figura se muestran los diagramas de los distintos casos que se presentan en la operación de inserción en árboles balanceados. 168 Ahora bien, para poder determinar si un árbol esta balanceado o no, se debe manejar información relativa al equilibrio de cada nodo del árbol. Surge así el concepto de factor de equilibrio de un nodo que se define como la altura del subárbol derecho menos la altura del subárbol izquierdo. FE = HRD – HRI Los valores validos que puede tomar el FE son ‐1, 0, 1. Si FE llegará a tomar los valores de 2 o ‐2, entonces debería reestructurarse el árbol. Reestructuración del árbol balanceado Reestructurar el árbol significa rotar los nodos del mismo para llevarlo a un estado de equilibrio. La rotación puede ser simple o compuesta. El primer caso involucra dos nodos y el segundo caso afecta a tres. Si la rotación es simple se puede realizar por las ramas derechas (DD) o por las ramas izquierdas (II). Si por otra parte la rotación es compuesta se puede realizar por las ramas derecha e izquierda (DI) o por las ramas izquierda y derecha (ID). DD Simple II Rotación Compuest a DI ID 169 Suponga que se desean insertar las siguientes claves en un árbol balanceado que se encuentra vacío: 65 – 50 – 23 – 70 – 82 – 68 ‐ 39 170 Eliminación en árboles balanceados La operación de eliminación en árboles balanceados, consiste en quitar un nodo del árbol sin violar los principios que definen a un árbol balanceado. En la operación de eliminación en árboles balanceados se deben distinguir los siguientes casos: Si el elemento a eliminar es terminal u hoja, simplemente se suprime. Si el elemento a eliminar tiene un solo descendiente, entonces se tiene que sustituir por ese descendiente. Si el elemento a eliminar tiene los dos descendientes, entonces se tiene que sustituir por el nodo que se encuentra más a la izquierda en el subárbol derecho o por el nodo que se encuentra más a la derecha en el subárbol izquierdo. Para eliminar un nodo en un árbol balanceado lo primero que se debe hacer es localizar su posición en el árbol. Se elimina siguiendo los criterios establecidos anteriormente y se regresa por el camino de búsqueda calculando el FE de los nodos visitados. Si en alguno de los nodos se viola el criterio de equilibrio, entonces se debe reestructurar el árbol. El proceso termina cuando se llega a la raíz del árbol. 171 4. Desarrollo Escriba un programa que implemente el funcionamiento de un árbol balanceado. El programa deberá mostrar un menú para realizar las operaciones de inserción, eliminación y recorrido del árbol. #include<iostream.h> #include<conio.h> #include<stdlib.h> void crea_avl(struct avl *, int, int); void elimina_avl(struct avl *, int, int); void reestructura_izq(struct avl *,int); void reestructura_der(struct avl *,int); void busqueda(struct avl *, int); void pre_orden(struct avl *); void in_orden(struct avl *); void pos_orden(struct avl *); int BO=0; struct avl { int info,FE; struct avl *izq, *der; }; void main() { clrscr(); struct avl *raiz; int resp,dato,opc,n=1,r; while(1) { cout<<"M E N U\\n1)Insertar\\n2)Eliminar\\n3)Recorrido\\n4)Busqueda\\n5)Salir\\nSeleccione una opcion: "; cin>>opc; switch(opc) { case 1: if(n==1) {raiz=new(avl); raiz‐>izq=NULL; raiz‐>der=NULL; cout<<"Teclea el valor del nodo raiz: "; cin>>raiz‐>info; n++; } else { cout<<"Tecle el valor del nodo: "; cin>>dato; crea_avl(raiz,BO,dato); } break; case 2: cout<<"Teclea el dato a eliminar: "; cin>>dato; elimina_avl(raiz,BO,dato); break; case 3: cout<<"Recorridos\\n1)Pre_orden\\n2)In_orden\\n3)Post_Orden\\nSelecciona un recorrido: "; cin>>r; switch(r) { case 1: pre_orden(raiz); break; case 2: in_orden(raiz); break; case 3: pos_orden(raiz); break; } break; case 4: cout<<"Teclea el dato a buscar: "; cin>>dato; busqueda(raiz,dato); break; case 5: 172 exit(0); break; } } void crea_avl(struct avl *nodo,int BO, int infor) { struct avl *nodo1, *nodo2; if(nodo != NULL) { if(infor < nodo‐>info) { crea_avl(nodo‐>izq,BO,infor); if(BO == 1) { if(nodo‐>FE == 1) { nodo‐>FE = 0; BO = 0; } if(nodo‐>FE == 0) nodo‐>FE = ‐1; if(nodo‐>FE == ‐1) nodo1 = nodo‐>izq; if(nodo1‐>FE <= 0) { nodo‐>izq = nodo1‐>der; nodo1‐>der = nodo; nodo‐>FE = 0; nodo = nodo1; } else { nodo2 = nodo1‐>der; nodo‐>izq = nodo2‐>der; nodo2‐>der = nodo; nodo1‐>der = nodo2‐>izq; nodo2‐>izq =nodo1; if(nodo2‐>FE == ‐1) nodo‐>FE = 1; else nodo‐>FE = 0; if(nodo2‐>FE == 1) nodo1‐>FE = ‐1; else nodo1‐>FE = 0; nodo = nodo2; } nodo‐ >FE = 0; BO = 0; } } else { if(infor > nodo‐>info) { crea_avl(nodo‐>der,BO,infor); if(BO == 1) { if(nodo‐>FE == ‐1) { nodo‐>FE = 0; BO = 0; } if(nodo‐>FE == 0) nodo‐>FE = 1; if(nodo‐>FE == 1) nodo1 = nodo‐>der; if(nodo1‐>FE >= 0) { nodo‐>der = nodo1‐>izq; nodo1‐>izq = nodo; else { nodo2 = nodo1‐>izq; nodo‐>der = nodo2‐>izq; nodo2‐>izq = nodo; nodo1‐>izq = nodo2‐>der; nodo2‐>der = nodo1; if(nodo2‐>FE == 1) nodo‐>FE = ‐1; else nodo‐>FE = 0; if(nodo2‐>FE == ‐1) nodo1‐>FE = 1; else nodo1‐>FE = 0; nodo = nodo2; } nodo‐>FE = 0; BO =0; } } else cout<<"La informacion ya se encuentra en el arbol!!!\n"; } } else { nodo=new(avl); nodo‐>info=infor; nodo >izq=NULL; 173 void elimina_avl(struct avl *nodo, int BO, int infor) { struct avl *aux, *aux1, *otro; int BOOL; if(nodo != NULL) { if(infor < nodo‐>info) elimina_avl(nodo‐>izq,BO,infor); else { if(infor > nodo‐>info) { elimina_avl(nodo‐>der, BO, infor); reestructura_izq(nodo,BO); } else { otro = nodo; BO = 1; if(otro‐>der ==NULL) nodo = otro‐>izq; else { if(otro‐>izq == NULL) nodo = otro‐>der; else { aux= nodo‐>izq; BOOL = 0; while(aux‐>der != NULL) { aux1 = aux; aux = aux‐>der; BOOL = 1; } nodo‐>info = aux ‐>info; otro = aux; if(BOOL == 1) aux1‐>der = aux‐>izq; else nodo‐>izq =aux‐>izq; reestructura_der(nodo‐>izq,BO); } } delete otro; } 174 void reestructura_izq(struct avl *nodo, int BO) { struct avl *nodo2, *nodo1; if(BO == 1) { if(nodo‐>FE == ‐1) nodo‐>FE = 0; if(nodo‐>FE == 0) { nodo‐>FE = 1; BO = 0; } if(nodo‐>FE == 1) nodo1 = nodo‐>der; if(nodo1‐>FE >= 0) { nodo‐>der = nodo1‐>izq; nodo1‐>izq = nodo; if(nodo1‐>FE == 0) { nodo‐>FE = 1; nodo1‐>FE = ‐1; BO = 0; } if(nodo1‐>FE == 1) { nodo‐>FE = 0; nodo1‐>FE = 0; } nodo = nodo1; } else { nodo2= nodo1‐>izq; nodo‐>der = nodo2‐>izq; nodo2‐>izq = nodo; nodo1‐>izq = nodo2‐>der; nodo2‐>der = nodo1; if(nodo2‐>FE == 1) nodo‐>FE = ‐1; else nodo‐>FE = 0; if(nodo2‐>FE == ‐1) nodo1‐>FE = 1; else 175 void reestructura_der(struct avl *nodo, int BO) { struct avl *nodo2, *nodo1; if(BO == 1) { if(nodo‐>FE == 1) nodo‐>FE = 0; if(nodo‐>FE == 0) { nodo‐>FE = ‐1; BO = 0; } if(nodo‐>FE == ‐1) nodo1 = nodo‐>izq; if(nodo1‐>FE <= 0) { nodo‐>izq = nodo1‐>der; nodo1‐>der = nodo; if(nodo1‐>FE == 0) { nodo‐>FE = ‐1; nodo1‐>FE = 1; BO = 0; } if(nodo1‐>FE == ‐1) { nodo‐>FE = 0; nodo1‐>FE = 0; } nodo = nodo1; } else { nodo2 = nodo1‐>der; nodo‐>izq = nodo2‐>der; nodo2‐>der = nodo; nodo1‐>der = nodo2‐>izq; nodo2‐>izq = nodo1; if(nodo2‐>FE == ‐1) nodo‐>FE = 1; else nodo‐>FE = 0; if(nodo2‐>FE == 1) nodo1‐>FE = ‐1; else nodo1‐>FE = 0; nodo = nodo2; nodo2‐>FE = 0; } } } 176 void busqueda(struct avl *nodo, int x) { if(x < nodo‐>info) { if(nodo‐>izq == NULL) cout<<"El nodo no se encuentra en el arbol!!!"; else busqueda(nodo‐>izq,x); } else { if(x > nodo‐>info) { if(nodo‐>der == NULL) cout<<"El nodo no se encuentra en el arbol!!!"; else busqueda(nodo‐>der,x); } else cout<<"El nodo si se encuentra en el arbol!!!"; } } void pre_orden(struct avl *nodo) { if(nodo != NULL) { cout<< nodo‐>info<<" "; pre_orden(nodo‐>izq); pre_orden(nodo‐>der); } } void in_orden(struct avl *nodo) { if(nodo != NULL) { in_orden(nodo‐>izq); cout<< nodo‐>info<<" "; in_orden(nodo‐>der); } } void pos_orden(struct avl *nodo) { if(nodo != NULL) { pos_orden(nodo‐>izq); pos_orden(nodo‐>der); cout<< nodo‐>info<<" "; } } 177 5. Cuestionario [Trabajo Complementario] 1. Mencione en donde se pueden aplicar la implementación y funcionamiento de los árboles balanceados. 2. Liste las ventajas de este tipo de estructura Vs. árboles binarios. 6. Conclusiones 178