PROGRAMACION III
FICN
Facultad de Ingeniera y Ciencias Naturales
GUIA # 7
TEMA:
RBOLES BINARIOS
OBJETIVOS: 1- Conocer la definicin de rboles binarios. 2- Comprender el concepto de equilibrio de rboles binarios y de expresin. 3- Ver y comprender la estructura de un rbol binario en c++ 4- Comprender el concepto de recorrido de un rbol y su aplicacin mediante ejemplos y ejercicios. 5- Desarrollar ejercicios usando las clases Nodo.h, Arbol.h
rboles Binarios Un rbol binario es una estructura recursiva. Cada nodo es la raz de su propio sub rbol y tiene hijos, que son races de rboles llamados sub rboles derecho e izquierdo del nodo. Un rbol binario se divide en tres subconjuntos distintos: {R} Nodo raz {I1, I2, In} Sub rbol izquierdo de R {D1, D2, Dn} Sub rbol derecho de R ______________________________________________________________________________1
PROGRAMACION III
FICN
Facultad de Ingeniera y Ciencias Naturales
GUIA # 7
EQUILIBRIO
Para determinar si un rbol esta en equilibrio, se calcula su factor de equilibrio. El factor de equilibrio de un rbol binario es la diferencia en altura entre dos sub rboles izquierdo y derecho. Si definimos la altura del sub rbol izquierdo como Hi y la altura del sub rbol derecho Hd, entonces el factor de equilibrio del rbol (B) se determina por la formula: B=Hi - Hd Ejemplo:
rbol A= - 2
rbol B = -1
rbol C = 1
Un rbol est equilibrado si su equilibrio o balance es cero y sus sub rboles son tambin equilibrados. Dado que esta definicin ocurre raramente se aplica definicin alternativa. Un rbol binario esta equilibrad si la altura de sus sub rboles difiere en no ms de uno (su factor de equilibrio es -1, 0, 0 + d) La clasificacin de los rboles binarios es: rbol binario completo: Tiene el nmero mximo de entradas para su altura. Esto sucede cuando el ltimo nivel est lleno. rbol binario degenerado: Es el caso en el que hay un solo nodo hoja y cada nodo hoja tiene un hijo, esto equivale a una lista enlazada rbol binario lleno: Es el que contiene 2n nodos a nivel n. ______________________________________________________________________________2
PROGRAMACION III
FICN
Facultad de Ingeniera y Ciencias Naturales
GUIA # 7
rbol completo
rbol degenerado
rbol Lleno
______________________________________________________________________________3
PROGRAMACION III
FICN
Facultad de Ingeniera y Ciencias Naturales
GUIA # 7
RBOLES DE EXPRESION
Una aplicacin muy importante de los rboles binarios son los rboles de expresin. Una expresin es una secuencia de tokens (componentes de lxicos) que siguen unas reglas prescritas. Un token puede ser bien un operador o un operando. Ejemplos: Dada la siguiente expresin: expresin.
______________________________________________________________________________4
PROGRAMACION III
FICN
Facultad de Ingeniera y Ciencias Naturales
GUIA # 7
La designacin tradicional de los recorridos utiliza un nombre para el nodo raz N, para el sub rbol izquierdo I, para el sub rbol derecho D, entonces: RECORRIDO PREORDEN: (nodo-izquierdo-derecho) RECORRIDO ENORDEN: (izquierdo-nodo-derecho) RECORRIDO POSTORDEN: (izquierdo-derecho-nodo) NID IND IDN
______________________________________________________________________________5
PROGRAMACION III
FICN
Facultad de Ingeniera y Ciencias Naturales
GUIA # 7
Ejemplo: Dado el siguiente rbol, realizar los recorridos preorden, postorden e inorden
EJERCICIOS
1) A continuacin se presentan las clases nodo y la clase Arbol completas, desarrolle los archivos cabecera correspondientes nodo.h y Arbol.h e implemente la clase rbol en un archivo cpp : Guia7.cpp en la cual desarrollar la aplicacin del ejercicio #2.
Clase nodo:
PROGRAMACION III
FICN
Facultad de Ingeniera y Ciencias Naturales
GUIA # 7
class Arbol{ private: Nodo *raiz; Nodo *actual; int contador; int altura; // Funciones auxiliares void Podar(Nodo* &nodo){ // Algoritmo recursivo, recorrido en postorden if(nodo){ Podar(nodo->izquierdo); // Podar izquierdo Podar(nodo->derecho); // Podar derecho delete nodo; // Eliminar nodo nodo = NULL; } } void auxContador(Nodo *nodo){ contador++; // Otro nodo // Continuar recorrido if(nodo->izquierdo) auxContador(nodo->izquierdo); if(nodo->derecho) auxContador(nodo->derecho); } void auxAltura(Nodo *nodo, int a){ // Recorrido postorden if(nodo->izquierdo) auxAltura(nodo->izquierdo, a+1); if(nodo->derecho) auxAltura(nodo->derecho, a+1); // Proceso, si es un nodo hoja, y su altura es mayor que la actual del // rbol, actualizamos la altura actual del rbol if(EsHoja(nodo) && a > altura) altura = a; } public: Arbol(){raiz = NULL; actual = NULL;} ~Arbol(){Podar(raiz); //el destructor elimina la raiz } // Insertar en rbol ordenado: void Insertar(const int dat){ Nodo *padre = NULL; actual = raiz; // Buscar el int en el rbol, manteniendo un puntero al nodo padre while (!Vacio(actual) && dat != actual->dato){ padre = actual; if (dat > actual->dato) actual = actual->derecho; else if (dat < actual->dato) actual = actual->izquierdo; } // Si se ha encontrado el elemento, regresar sin insertar if(!Vacio(actual)) return; // Si padre es NULL, entonces el rbol estaba vaco, el nuevo nodo ser
______________________________________________________________________________7
PROGRAMACION III
FICN
Facultad de Ingeniera y Ciencias Naturales
GUIA # 7
// el nodo raiz if (Vacio(padre)) raiz = new Nodo(dat); // Si el int es menor que el que contiene el nodo padre, lo insertamos // en la rama izquierda else if (dat < padre->dato) padre->izquierdo = new Nodo(dat); // Si el int es mayor que el que contiene el nodo padre, lo insertamos // en la rama derecha else if(dat > padre->dato) padre->derecho = new Nodo(dat); } // Borrar un elemento del rbol: void Borrar(const int dat){ Nodo *padre = NULL; Nodo *nodo; int aux; actual = raiz; // Mientras sea posible que el valor est en el rbol while(!Vacio(actual)) { if(dat == actual->dato) { // Si el valor est en el nodo actual if(EsHoja(actual)) { // Y si adems es un nodo hoja: lo borramos if(padre) // Si tiene padre (no es el nodo raiz) // Anulamos el puntero que le hace referencia if(padre->derecho == actual) padre->derecho = NULL; else if(padre->izquierdo == actual) padre->izquierdo = NULL; delete actual; // Borrar el nodo actual = NULL; return; } else { // Si el valor est en el nodo actual, pero no es hoja // Buscar nodo padre = actual; // Buscar nodo ms izquierdo de rama derecha if(actual->derecho) { nodo = actual->derecho; while(nodo->izquierdo) { padre = nodo; nodo = nodo->izquierdo; } } // O buscar nodo ms derecho de rama izquierda else { nodo = actual->izquierdo; while(nodo->derecho) { padre = nodo; nodo = nodo->derecho;
______________________________________________________________________________8
PROGRAMACION III
FICN
Facultad de Ingeniera y Ciencias Naturales
GUIA # 7
} } aux = actual->dato; actual->dato = nodo->dato; nodo->dato = aux; actual = nodo; } } else { padre = actual; if(dat > actual->dato) actual = actual->derecho; else if(dat < actual->dato) actual = actual->izquierdo; } } } // Funcin de bsqueda: bool Buscar(const int dat){ actual = raiz; // Todava puede aparecer, ya que quedan nodos por mirar while(!Vacio(actual)) { if(dat == actual->dato) return true; // int encontrado else if(dat > actual->dato) actual = actual->derecho; // Seguir else if(dat < actual->dato) actual = actual->izquierdo; } return false; // No est en rbol } // Comprobar si el rbol est vaco: bool Vacio(Nodo *r){ return r==NULL; } // Comprobar si es un nodo hoja: bool EsHoja(Nodo *r){ return !r->derecho && !r->izquierdo; } // Contar nmero de nodos: const int NumeroNodos(){ contador = 0; auxContador(raiz); // FUncin auxiliar return contador; } const int AlturaArbol(){ altura = 0; auxAltura(raiz, 0); // Funcin auxiliar return altura; }
______________________________________________________________________________9
PROGRAMACION III
FICN
Facultad de Ingeniera y Ciencias Naturales
GUIA # 7
// Todava puede aparecer, ya que quedan nodos por mirar while(!Vacio(actual)) { if(dat == actual->dato) return altura; // int encontrado else { altura++; // Incrementamos la altura, seguimos buscando if(dat > actual->dato) actual = actual->derecho; else if(dat < actual->dato) actual = actual->izquierdo; } } return -1; // No est en rbol } // Devolver referencia al int del nodo actual: int &ValorActual(){ return actual->dato; } // Moverse al nodo raiz: void Raiz(){ actual = raiz; } // Aplicar una funcin a cada elemento del rbol: void InOrden(void (*func)(int&) , Nodo *nodo=NULL, bool r=true){ if(r) nodo = raiz; if(nodo->izquierdo) InOrden(func, nodo->izquierdo, false); func(nodo->dato); if(nodo->derecho) InOrden(func, nodo->derecho, false); } void PreOrden(void (*func)(int&) , Nodo *nodo=NULL, bool r=true){ if(r) nodo = raiz; func(nodo->dato); if(nodo->izquierdo) PreOrden(func, nodo->izquierdo, false); if(nodo->derecho) PreOrden(func, nodo->derecho, false); } void PostOrden(void (*func)(int&) , Nodo *nodo=NULL, bool r=true){ if(r) nodo = raiz; if(nodo->izquierdo) PostOrden(func, nodo->izquierdo, false); if(nodo->derecho) PostOrden(func, nodo->derecho, false); func(nodo->dato); } };
______________________________________________________________________________10
PROGRAMACION III
FICN
Facultad de Ingeniera y Ciencias Naturales
GUIA # 7
2) Cree una aplicacin con un men con las siguientes opciones y que funcione:
REFERENCIA
A. 1- Programacin en C++. Algoritmos, estructuras de datos y objetos. Luis Joyanes Aguilar McGrawHill ao 2000 1 Ed. B. Cap. 6 rboles [En lnea]. Disponible en http://c.conclase.net/edd/?cap=006#inicio visitado el 08 /01/12. C. rboles. [En lnea]. Disponible en http://www.algoritmia.net/articles.php?id=17 visitado el 07/01/12.
______________________________________________________________________________11