Anda di halaman 1dari 14

// Plantilla de Arbol Binario de Bsqueda en C++ // (C) Abril 2002, Salvador Pozo // C con Clase: http://c.conclase.

net

#include <iostream> using namespace std;

class ArbolABB { private: //// Clase local de Lista para Nodo de ArbolBinario: class Nodo { public: // Constructor: Nodo(const int dat, Nodo *izq=NULL, Nodo *der=NULL) : dato(dat), izquierdo(izq), derecho(der) {} // Miembros: int dato; Nodo *izquierdo; Nodo *derecho; };

// Punteros de la lista, para cabeza y nodo actual: Nodo *raiz; Nodo *actual; int contador; int altura;

public: // Constructor y destructor bsicos: ArbolABB() : raiz(NULL), actual(NULL) {} ~ArbolABB() { Podar(raiz); } // Insertar en rbol ordenado: void Insertar(const int dat); // Borrar un elemento del rbol: void Borrar(const int dat); // Funcin de bsqueda: bool Buscar(const int dat); // 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(); const int AlturaArbol(); // Calcular altura de un int: int Altura(const int dat); // 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);

void PreOrden(void (*func)(int&) , Nodo *nodo=NULL, bool r=true); void PostOrden(void (*func)(int&) , Nodo *nodo=NULL, bool r=true); private: // Funciones auxiliares void Podar(Nodo* &); void auxContador(Nodo*); void auxAltura(Nodo*, int); };

// Poda: borrar todos los nodos a partir de uno, incluido void ArbolABB::Podar(Nodo* &nodo) { // Algoritmo recursivo, recorrido en postorden if(nodo) { Podar(nodo->izquierdo); // Podar izquierdo Podar(nodo->derecho); // Podar derecho delete nodo; nodo = NULL; } } // Eliminar nodo

// Insertar un int en el rbol ABB void ArbolABB::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 // 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); }

// Eliminar un elemento de un rbol ABB void ArbolABB::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; } } // Intercambiar valores de no a borrar u nodo encontrado // y continuar, cerrando el bucle. El nodo encontrado no tiene // por qu ser un nodo hoja, cerrando el bucle nos aseguramos // de que slo se eliminan nodos hoja. aux = actual->dato; actual->dato = nodo->dato; nodo->dato = aux; actual = nodo; } } else { // Todava no hemos encontrado el valor, seguir buscndolo padre = actual; if(dat > actual->dato) actual = actual->derecho; else if(dat < actual->dato) actual = actual->izquierdo; } } }

// Recorrido de rbol en inorden, aplicamos la funcin func, que tiene // el prototipo: // void func(int&); void ArbolABB::InOrden(void (*func)(int&) , Nodo *nodo, bool r) { if(r) nodo = raiz; if(nodo->izquierdo) InOrden(func, nodo->izquierdo, false); func(nodo->dato); if(nodo->derecho) InOrden(func, nodo->derecho, false); }

// Recorrido de rbol en preorden, aplicamos la funcin func, que tiene // el prototipo: // void func(int&); void ArbolABB::PreOrden(void (*func)(int&), Nodo *nodo, bool r) { if(r) nodo = raiz; func(nodo->dato); if(nodo->izquierdo) PreOrden(func, nodo->izquierdo, false); if(nodo->derecho) PreOrden(func, nodo->derecho, false); }

// Recorrido de rbol en postorden, aplicamos la funcin func, que tiene // el prototipo: // void func(int&); void ArbolABB::PostOrden(void (*func)(int&), Nodo *nodo, bool r)

{ if(r) nodo = raiz; if(nodo->izquierdo) PostOrden(func, nodo->izquierdo, false); if(nodo->derecho) PostOrden(func, nodo->derecho, false); func(nodo->dato); }

// Buscar un valor en el rbol bool ArbolABB::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 }

// Calcular la altura del nodo que contiene el int dat int ArbolABB::Altura(const int dat) { int altura = 0; actual = raiz;

// 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 }

// Contar el nmero de nodos const int ArbolABB::NumeroNodos() { contador = 0;

auxContador(raiz); // FUncin auxiliar return contador; }

// Funcin auxiliar para contar nodos. Funcin recursiva de recorrido en // preorden, el proceso es aumentar el contador void ArbolABB::auxContador(Nodo *nodo) {

contador++; // Otro nodo // Continuar recorrido if(nodo->izquierdo) auxContador(nodo->izquierdo); if(nodo->derecho) auxContador(nodo->derecho); }

// Calcular la altura del rbol, que es la altura del nodo de mayor altura. const int ArbolABB::AlturaArbol() { altura = 0;

auxAltura(raiz, 0); // Funcin auxiliar return altura; }

// Funcin auxiliar para calcular altura. Funcin recursiva de recorrido en // postorden, el proceso es actualizar la altura slo en nodos hojas de mayor // altura de la mxima actual void ArbolABB::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;

// Funcin de prueba para recorridos del rbol void Mostrar(int &d) { cout << d << ","; }

int main() { // Un rbol de enteros ArbolABB ArbolInt;

// Insercin de nodos en rbol: ArbolInt.Insertar(10); ArbolInt.Insertar(5); ArbolInt.Insertar(12); ArbolInt.Insertar(4); ArbolInt.Insertar(7); ArbolInt.Insertar(3); ArbolInt.Insertar(6); ArbolInt.Insertar(9); ArbolInt.Insertar(8); ArbolInt.Insertar(11); ArbolInt.Insertar(14); ArbolInt.Insertar(13);

ArbolInt.Insertar(2); ArbolInt.Insertar(1); ArbolInt.Insertar(15); ArbolInt.Insertar(10); ArbolInt.Insertar(17); ArbolInt.Insertar(18); ArbolInt.Insertar(16);

cout << "Altura de arbol " << ArbolInt.AlturaArbol() << endl;

// Mostrar el rbol en tres ordenes distintos: cout << "InOrden: "; ArbolInt.InOrden(Mostrar); cout << endl; cout << "PreOrden: "; ArbolInt.PreOrden(Mostrar); cout << endl; cout << "PostOrden: "; ArbolInt.PostOrden(Mostrar); cout << endl;

// Borraremos algunos elementos: cout << "N nodos: " << ArbolInt.NumeroNodos() << endl; ArbolInt.Borrar(5); cout << "Borrar 5: "; ArbolInt.InOrden(Mostrar);

cout << endl; ArbolInt.Borrar(8); cout << "Borrar 8: "; ArbolInt.InOrden(Mostrar); cout << endl; ArbolInt.Borrar(15); cout << "Borrar 15: "; ArbolInt.InOrden(Mostrar); cout << endl; ArbolInt.Borrar(245); cout << "Borrar 245: "; ArbolInt.InOrden(Mostrar); cout << endl; ArbolInt.Borrar(4); cout << "Borrar 4: "; ArbolInt.InOrden(Mostrar); ArbolInt.Borrar(17); cout << endl; cout << "Borrar 17: "; ArbolInt.InOrden(Mostrar); cout << endl;

// Veamos algunos parmetros cout << "N nodos: " << ArbolInt.NumeroNodos() << endl; cout << "Altura de 1 " << ArbolInt.Altura(1) << endl; cout << "Altura de 10 " << ArbolInt.Altura(10) << endl;

cout << "Altura de arbol " << ArbolInt.AlturaArbol() << endl;

cin.get(); return 0; }

Anda mungkin juga menyukai