You are on page 1of 57

ayuda para comparar 2 arboles binarios

« en: 29 Diciembre 2013, 13:35 »

Hola, estoy con problemas para comparar 2 arboles binarios, al intentar


compararlos, deberia devolverme 0 si son iguales, 1 si son distintos, pero el
programa solo me devuelve el lado de la derecha y no compara la izq, espero
puedan ayudarme

Código

1. int iguales(arbol *a, arbol *b){


2. if(a == NULL && b ==NULL){
3. return 0;
4. } else {
5. if(a == NULL || b == NULL){
6. return 1;
7. } else {
8. if(a->dato == b->dato){
9. iguales(a->izq, b->izq);
10. iguales(a->der, b->der);
11. } else {
12. return 1;
13. }
14. }
15. }

* C++ - Arboles Binaros de busqueda -Recorridos por amplitud


*
* Copyright 2014 Martin Cruz Otiniano
*
* Description: Recorrdos por Orden, Pre-Orden y Post-Orden
*
* Site: martincruz.me
*/

#include <iostream>
#include <cstdlib>
using namespace std;

struct nodo{
int nro;
struct nodo *izq, *der;
};

typedef struct nodo *ABB;


/* es un puntero de tipo nodo que hemos llamado ABB, que ulitizaremos
para mayor facilidad de creacion de variables */

ABB crearNodo(int x)
{
ABB nuevoNodo = new(struct nodo);
nuevoNodo->nro = x;
nuevoNodo->izq = NULL;
nuevoNodo->der = NULL;

return nuevoNodo;
}
void insertar(ABB &arbol, int x)
{
if(arbol==NULL)
{
arbol = crearNodo(x);
}
else if(x < arbol->nro)
insertar(arbol->izq, x);
else if(x > arbol->nro)
insertar(arbol->der, x);
}

void preOrden(ABB arbol)


{
if(arbol!=NULL)
{
cout << arbol->nro <<" ";
preOrden(arbol->izq);
preOrden(arbol->der);
}
}

void enOrden(ABB arbol)


{
if(arbol!=NULL)
{
enOrden(arbol->izq);
cout << arbol->nro << " ";
enOrden(arbol->der);
}
}

void postOrden(ABB arbol)


{
if(arbol!=NULL)
{
postOrden(arbol->izq);
postOrden(arbol->der);
cout << arbol->nro << " ";
}
}

void verArbol(ABB arbol, int n)


{
if(arbol==NULL)
return;
verArbol(arbol->der, n+1);

for(int i=0; i<n; i++)


cout<<" ";

cout<< arbol->nro <<endl;

verArbol(arbol->izq, n+1);
}
int main()
{
ABB arbol = NULL; // creado Arbol

int n; // numero de nodos del arbol


int x; // elemento a insertar en cada nodo

cout << "\n\t\t ..[ ARBOL BINARIO DE BUSQUEDA ].. \n\n";

cout << " Numero de nodos del arbol: ";


cin >> n;
cout << endl;

for(int i=0; i<n; i++)


{
cout << " Numero del nodo " << i+1 << ": ";
cin >> x;
insertar( arbol, x);
}

cout << "\n Mostrando ABB \n\n";


verArbol( arbol, 0);

cout << "\n Recorridos del ABB";

cout << "\n\n En orden : "; enOrden(arbol);


cout << "\n\n Pre Orden : "; preOrden(arbol);
cout << "\n\n Post Orden : "; postOrden(arbol);

cout << endl << endl;

system("pause");
return 0;
}

ARBOLES BINARIOS DE BUSQUEDA

1. INTRODUCCIÓN.
La búsqueda en árboles binarios es un método de búsqueda simple, dinámico y
eficiente considerado como uno de los fundamentales en Ciencia de la
Computación. De toda la terminología sobre árboles,tan sólo recordar que la
propiedad que define un árbol binario es que cada nodo tiene a lo más un hijo a la
izquierda y uno a la derecha.Para construir los algoritmos consideraremos que
cada nodo contiene un registro con un valor clave a través del cual efectuaremos
las búsquedas.En las implementaciones que presentaremos sólo se considerará en
cada nodo del árbol un valor del tipo tElemento aunque en un caso general ese
tipo estará compuesto por dos:una clave indicando el campo por el cual se realiza
la ordenación y una información asociada a dicha clave o visto de otra forma,una
información que puede ser compuesta en la cual existe definido un orden.

Un árbol binario de búsqueda(ABB) es un árbol binario con la propiedad de que


todos los elementos almacenados en el subárbol izquierdo de cualquier
nodo x son menores que el elemento almacenado en x ,y todos los elementos
almacenados en el subárbol derecho de x son mayores que el elemento
almacenado en x.

La figura 1 muestra dos ABB construidos en base al mismo conjunto de enteros:


Obsérvese la interesante propiedad de que si se listan los nodos del ABB en
inorden nos da la lista de nodos ordenada.Esta propiedad define un método de
ordenación similar al Quicksort,con el nodo raíz jugando un papel similar al del
elemento de partición del Quicksort aunque con los ABB hay un gasto extra de
memoria mayor debido a los punteros.La propiedad de ABB hace que sea muy
simple diseñar un procedimiento para realizar la búsqueda. Para determinar
si k está presente en el árbol la comparamos con la clave situada en la raíz, r.Si
coinciden la búsqueda finaliza con éxito, si k<r es evidente que k,de estar
presente,ha de ser un descendiente del hijo izquierdo de la raíz,y si es mayor será
un descendiente del hijo derecho.La función puede ser codificada fácilmente de
la siguiente forma:
#define ABB_VACIO NULL
#define TRUE 1
#define FALSE 0

typedef int tEtiqueta /*Algun tipo adecuado*/


typedef struct tipoceldaABB{
struct tipoceldaABB *hizqda,*hdrcha;
tEtiqueta etiqueta;
}*nodoABB;
typedef nodoABB ABB;

ABB Crear(tEtiqueta et)


{
ABB raiz;

raiz = (ABB)malloc(sizeof(struct tceldaABB));


if (raiz == NULL)
error("Memoria Insuficiente.");
raiz->hizda = NODO_NULO;
raiz->hdcha = NODO_NULO;
raiz->etiqueta = et;
return(raiz);
}

int Pertenece(tElemento x,ABB t)


{

if(!t)
return FALSE
else if(t->etiqueta==x)
return TRUE;
else if(t->etiqueta>x)
return pertenece(x,t->hizqda);
else return pertenece(x,t->hdrcha);
}

Es conveniente hacer notar la diferencia entre este procedimiento y el de


búsqueda binaria.En éste podría pensarse en que se usa un árbol binario para
describir la secuencia de comparaciones hecha por una función de búsqueda
sobre el vector.En cambio en los ABB se construye una estructura de datos con
registros conectados por punteros y se usa esta estructura para la búsqueda.El
procedimiento de construcción de un ABB puede basarse en un procedimiento de
inserción que vaya añadiendo elementos al árbol. Tal procedimiento comenzaría
mirando si el árbol es vacío y de ser así se crearía un nuevo nodo para el
elemento insertado devolviendo como árbol resultado un puntero a ese nodo.Si el
árbol no está vacio se busca el elemento a insertar como lo hace el
procedimiento pertenece sólo que al encontrar un puntero NULL durante la
búsqueda,se reemplaza por un puntero a un nodo nuevo que contenga el elemento
a insertar.El código podría ser el siguiente:
void Inserta(tElemento x,ABB *t)
{

if(!(*t)){
*t=(nodoABB)malloc(sizeof(struct tipoceldaABB));
if(!(*t)){
error("Memoria Insuficiente.");
}
(*t)->etiqueta=x;
(*t)->hizqda=NULL;
(*t)->hdrcha=NULL;
} else if(x<(*t)->etiqueta)
inserta(x,&((*t)->hizqda));
else
inserta(x,&((*t)->hdrcha));
}

Por ejemplo supongamos que queremos construir un ABB a partir del conjunto
de enteros {10,5,14,7,12} aplicando reiteradamente el proceso de inserción.El
resultado es el que muestra la figura 2.

2. ANÁLISIS DE LA EFICIENCIA DE LAS


OPERACIONES.
Puede probarse que una búsqueda o una inserción en un ABB
requiere O(log2n) operaciones en el caso medio,en un árbol construido a partir
de n claves aleatorias, y en el peor caso una búsqueda en un ABB con n claves
puede implicar revisar las n claves,o sea,es O(n).

Es fácil ver que si un árbol binario con n nodos está completo (todos los nodos no
hojas tienen dos hijos) y así ningún camino tendrá más de 1+log2n nodos.Por
otro lado,las operaciones pertenece e inserta toman una cantidad de tiempo
constante en un nodo.Por tanto,en estos árboles, el camino que forman desde la
raíz,la secuencia de nodos que determinan la búsqueda o la inserción, es de
longitud O(log2n),y el tiempo total consumido para seguir el camino es
también O(log2n).

Sin embargo,al insertar n elementos en un orden aleatorio no es seguro que se


sitúen en forma de árbol binario completo.Por ejemplo,si sucede que el primer
elemento(de n situados en orden) insertado es el más pequeño el árbol resultante
será una cadena de n nodos donde cada nodo,excepto el más bajo en el
árbol,tendrá un hijo derecho pero no un hijo izquierdo.En este caso,es fácil
demostrar que como lleva i pasos insertar el i-ésimo elemento dicho proceso
de n inserciones necesita pasos o equivalentemente O(n) pasos
por operación.

Es necesario pues determinar si el ABB promedio con n nodos se acerca en


estructura al árbol completo o a la cadena,es decir,si el tiempo medio por
operación es O(log2n),O(n) o una cantidad intermedia.Como es difícil saber la
verdadera frecuencia de inserciones sólo se puede analizar la longitud del camino
promedio de árboles "aleatorios" adoptando algunas suposiciones como que los
árboles se forman sólo a partir de inserciones y que todas las magnitudes de
los n elementos insertados tienen igual probabilidad.Con esas suposiciones se
puede calcular P(n),el número promedio de nodos del camino que va de la raíz
hacia algún nodo(no necesariamente una hoja).Se supone que el árbol se formó
con la inserción aleatoria de n nodos en un árbol que se encontraba inicialmente
vacío,es evidente que P(0)=0 y P(1)=1.Supongamos que tenemos una lista
de n>=2 elementos para insertar en un árbol vacío,el primer elemento de la
lista,x,es igual de probable que sea el primero,el segundo o el n-ésimo en la lista
ordenada.Consideremos que i elementos de la lista son menores que x de modo
que n-i-1 son mayores. Al construir el árbol,x aparecerá en la raíz,los i elementos
más pequeños serán descendientes izquierdos de la raíz y los restantes n-i-1 serán
descendientes derechos.Esquemáticamente quedaría como muestra la figura 3.
Al tener tanto en un lado como en otro todos los elementos igual probabilidad se
espera que los subárboles izqdo y drcho de la raíz tengan longitudes de camino
medias P(i) y P(n-i-1) respectivamente.Como es posible acceder a esos
elementos desde la raíz del árbol completo es necesario agregar 1 al número de
nodos de cada camino de forma que para todo i entre 0 y n-1,P(n) puede
calcularse obteniendo el promedio de la suma:

El primer término es la longitud del camino promedio en el subárbol izquierdo


ponderando su tamaño.El segundo término es la cantidad análoga del subárbol
derecho y el término 1/n representa la contribución de la raíz.Al promediar la
suma anterior para todo i entre 1 y n se obtiene la recurrencia:

y con unas transformaciones simples podemos ponerla en la forma:


y el resto es demostrar por inducción sobre n que P(n)<=1+4log2n.

En consecuencia el tiempo promedio para seguir un camino de la raíz a un nodo


aleatorio de un ABB construido mediante inserciones aleatorias es O(log2n).Un
análisis más detallado demuestra que la constante 4 es en realidad una constante
cercana a 1.4.

De lo anterior podemos concluir que la prueba de pertenencia de una clave


aleatoria lleva un tiempo O(log2n).Un análisis similar muestra que si se incluyen
en la longitud del camino promedio sólo aquellos nodos que carecen de ambos
hijos o solo aquellos que no tienen hijo izqdo o drcho también la longitud
es O(log2n).

Terminaremos este apartado con algunos comentarios sobre los borrados en los
ABB.Es evidente que si el elemento a borrar está en una hoja bastaría
eliminarla,pero si el elemento está en un nodo interior,eliminándolo,podríamos
desconectar el árbol.Para evitar que esto suceda se sigue el siguiente
procedimiento:si el nodo a borrar u tiene sólo un hijo se sustituye u por ese hijo y
el ABB quedar&aacue; construido.Si u tiene dos hijos,se encuentra el menor
elemento de los descendientes del hijo derecho(o el mayor de los descendientes
del hijo izquierdo) y se coloca en lugar de u,de forma que se continúe
manteniendo la propiedad de ABB.

Tutor de Estructuras de Datos Interactivo


Exposito Lopez Daniel, Abraham García Soto, Martin Gomez Antonio Jose
Director de proyecto: Joaquín Fernández Valdivia
5º Licenciatura Informatica
ETSII 99/00 (Universidad de Granada).
Estructura de datos – Árboles
agosto 22, 2014 Oscar Blancarte Estructuras de Datos

Los Árboles son las estructuras de datos mas utilizadas, pero también una de las mas
complejas, Los Árboles se caracterizan por almacenar sus nodos en forma jerárquica y no en
forma lineal como las Listas Ligadas, Colas,Pilas,etc., de las cuales ya hemos hablado en días
pasados.
Fig. 1: La imagen muestra la diferencia entra las estructuras de datos lineas y las no lineales
como lo son los Árboles.

Datos importantes de los Árboles


Para comprender mejor que es un árbol comenzaremos explicando como está estructurado.
Nodos: Se le llama Nodo a cada elemento que contiene un Árbol.
Nodo Raíz: Se refiere al primer nodo de un Árbol, Solo un nodo del Árbol puede ser la Raíz.
Nodo Padre: Se utiliza este termino para llamar a todos aquellos nodos que tiene al menos un
hijo.
Nodo Hijo: Los hijos son todos aquellos nodos que tiene un padre.
Nodo Hermano: Los nodos hermanos son aquellos nodos que comparte a un mismo padre en
común dentro de la estructura.
Nodo Hoja: Son todos aquellos nodos que no tienen hijos, los cuales siempre se encuentran
en los extremos de la estructura.
Nodo Rama: Estos son todos aquellos nodos que no son la raíz y que ademas tiene al menos
un hijo.

Fig.
2: La imagen muestra de forma gráfica cuales son los nodos Raíz, Rama, Hoja.

Fig.3: La siguiente imagen muestra de forma gráfica los nodos Padre, Hijo y Hermanos
Los arboles a demas de los nodos tiene otras propiedades importantes que son utilizadas en
diferente ámbitos los cuales son:
Nivel: Nos referimos como nivel a cada generación dentro del árbol. Por ejemplo, cuando a un
nodo hoja le agregamos un hijo, el nodo hoja pasa a ser un nodo rama pero a demas el árbol
crece una generación por lo que el Árbol tiene un nivel mas.Cada generación tiene un número
de Nivel distinto que las demas generaciones.
 Un árbol vacío tiene 0 niveles
 El nivel de la Raíz es 1
 El nivel de cada nodo se calculado contando cuantos nodos existen sobre el, hasta
llegar a la raíz + 1, y de forma inversa también se podría, contar cuantos nodos existes
desde la raíz hasta el nodo buscado + 1.

Altura: Le llamamos Altura al número máximo de niveles de un Árbol.

Fig. 4: En la imagen se muestran los Niveles y la Altura de un Árbol.


La altura es calculado mediante recursividad tomando el nivel mas grande de los dos sub-
árboles de forma recursiva de la siguiente manera:
altura = max(altura(hijo1), altura(hijo2),altura(hijoN)) + 1
Peso: Conocemos como peso a el número de nodos que tiene un Árbol. Este factor es
importante por que nos da una idea del tamaño del árbol y el tamaño en memoria que nos puede
ocupar en tiempo de ejecución(Complejidad Espacial en análisis de algoritmos.)
Fig. 5: La
imagen nos muestra como se calcula el peso de un Árbol, el cual es la suma de todos sus
nodos, sin importar el orden en que sean contados.
El peso se puede calcular mediante cualquier tipo de recorrido el cual valla contando los nodo
a medida que avanza sobre la estructura. El peso es un árbol es igual a la suma del peso de los
sub-árboles hijos + 1
peso = peso(hijo1) + peso(hijo2) + peso(hijoN)+ 1
Nota: Los tipos de recorridos los veremos mas adelante.
Orden: El Orden de un árbol es el número máximo de hijos que puede tener un Nodo.

Fig. 6:
Imagen que nuestra dos Árboles con Orden = 2(Izquierda) y un segundo con Orden =
3(Derecha).
Notemos que un Árbol con Orden = 1 no tendría sentido ya que seria una estructura lineal. ya
que cada nodo solo podría tener un Hijo y tendríamos un Árbol como la Imagen de la Fig.1.
Este valor no lo calculamos, si no que ya lo debemos conocer cuando diseñamos nuestra
estructura, ya que si queremos calcular esto lo que obtendremos es el grado(hablamos de el
continuación).
Grado: El grado se refiere al número mayor de hijos que tiene alguno de los nodos del Árbol y
esta limitado por el Orden, ya que este indica el número máximo de hijos que puede tener un
nodo.

Fig. 7:
En la imagen podemos apreciar un Árbol con grado 2(Izquierda) y un otro con grado
3(Derecha).
El grado se calcula contando de forma recursiva el número de hijos de cada sub-árbol hijo y el
numero de hijos del nodo actual para tomar el mayor, esta operación se hace de forma recursiva
para recorrer todo el árbol.
grado = max(contarHijos(hijo1),contarHijos(hijo2), contarHijos(hijoN), contarHijos(this))
Sub-Árbol: Conocemos como Sub-Árbol a todo Árbol generado a partir de una sección
determinada del Árbol, Por lo que podemos decir que un Árbol es un nodo Raíz con N Sub-
Árboles.
Fig. 8: En la imagen de puede apreciar que un Árbol esta compuesto por una seria de Sub-
Arboles los cual conforman toda la estructura.
Existen escenarios donde podemos sacar un Sub-Árboles del Árbol para procesarlo de forma
separada, de esta forma el Sub-Árboles pasa a ser un Árbol independiente, También podemos
eliminar Sub-Árboles completos, Agregarlos,entre otras operaciones.

Árbol n-ario
los arboles n-arios son aquellos arboles donde el número máximo de hijos por nodo es de N,
en la figura 7 podemos apreciar dos árboles con grado 2 y grado 3, estos dos arboles también
los podemos definir como Árbol n-ario con n = 2 y n=3 respectivamente.

Árboles binarios
Esta estructura se caracteriza por que cada nodo solo puede tener máximo 2 hijo, dicho de otra
manera es un Árbol n-ario de Grado 2.
Fig. 9: En la imagen podemos apreciar un Árbol Binario.

Árbol binario lleno: Es aquel que el que todos los nodos tiene cero o 2 hijos con excepción de
la Raíz.

Fig. 10: Podemos


apreciar que el árbol de la derecha no esta lleno ya que uno de sus nodos no cumple con la
condición cero o 2 hijos. ya que el nodo C solo tiene un hijo.
Árbol binario perfecto: Es un Árbol lleno en donde todos las Hojas están en el mismo Nivel.
Fig. 11: En la imagen podemos apreciar que el árbol de la izquierda tiene todas sus hojas al
mismo nivel y que ademas esta lleno, lo que lo convierte en un árbol binario perfecto. Sin
embargo, del lado derecho podemos ver que aunque el árbol esta lleno no tiene todas las
hojas al mismo nivel lo que hace que no sea un árbol binario perfecto pero si lleno.

Recorrido sobre Árboles


Los recorridos son algoritmos que nos permiten recorrer un árbol en un orden especifico, los
recorridos nos pueden ayudar encontrar un nodo en el árbol, o buscar una posición determinada
para insertar o eliminar un nodo.
Básicamente podemos catalogar las búsqueda en dos tipos, las búsqueda en profundidad y las
búsquedas en amplitud.

Búsquedas no informadas
Las búsquedas no informadas son aquellas en que se realiza el viaje por todo el árbol sin tener
una pista de donde pueda estar el dato deseado. Este tipo de búsquedas también se conocen
como búsquedas a ciegas.
Para comprender mejor que es una búsqueda no informada expondremos el siguiente ejemplo:
Imagine que vamos por la carretera y de repente encontramos dos caminos, el problema a qui
es que uno después de 50 kilómetros esta en construcción y el otro nos lleva a nuestro destino,
sin embargo ninguno de los caminos tiene señalamiento. Lo que tendríamos que hacer es
recorrer el primero camino y después de 50 kilómetros encontrarnos con que el camino esta en
construcción, entonces tendríamos que regresar para irnos por el segundo camino,el cual nos
lleva a nuestro destino(Para esto ya recorrimos los 50 kilómetros de ida y los 50 kilómetros de
regreso lo que nos da 100 kilómetros mas a nuestra ruta).
A este tipo de escenarios en los cuales las búsquedas de hacen a ciegas los conocemos como
búsquedas no informadas.
Las siguientes métodos de búsqueda que veremos a continuación(Búsqueda en profundad y
Búsqueda en amplitud) pertenecen a las búsquedas no informadas.

Búsqueda en profundidad
Recorrido Pre-orden: El recorrido inicia en la Raíz y luego se recorre en pre-orden cada
unos de los sub-árboles de izquierda a derecha.
Esta definición puede ser un poco compleja de entender por lo que mejor les dejo la siguiente
imagen.

Fig. 12:En la imagen podemos ver el orden en que es recorrido el árbol iniciando desde la
Raíz.

Fig. 13: Codigo de una función


recursiva que recorre un árbol en preorden.
Recorrido Pos-orden: Se recorre el pos-orden cada uno de los sub-árboles y al final se recorre
la raíz.
Para comprender mejor esta definición observemos la siguiente imagen:
Fig. 14: En la imagen podemos observar como se realiza el recorrido en Pos-Orden, Sin
embargo es importante notar que el primer nodo que se imprime no es la Raiz pues en este
recorrido la Raíz de cada Sub-Árbol es procesado al final, ya que toda su descendencia ha

sido procesada. Fig. 15: Código


de una función recursiva que recorre un árbol en posorden
Recorrido in-orden: Se recorre en in-orden el primer sub-árbol, luego se recorre la raíz y al
final se recorre en in-orden los demas sub-árboles
Fig. 16:En la imagen se muestra como es el recorrido In-Orden, Podemos apreciar que la Raíz
no es el primero elemento en ser impreso pues este recorrido recorre su rama izquierda, luego
la raíz del sub-árbol y luego la rama derecha.

Fig. 17: Código de una función


recursiva que recorre un árbol en inorden

Búsqueda en amplitud.
Se recorre primero la raíz, luego se recorren los demas nodos ordenados por el nivel al que
pertenecen en orden de Izquierda a derecha.
Este tipo de búsqueda se caracteriza por que la búsqueda se hace nivel por nivel y de izquierda
a derecha.
Fig. 18: En la
imagen se observa como es que un nodo es buscado mediante la búsqueda en profundidad.

En la imagen podemos observa que el árbol es recorrido en su totalidad pero esto no siempre
es a sí, ya que el algoritmo se detiene cuando el elemento buscado es encontrado.

Fig. 19: Código de


un función que recorre el árbol en amplitud.

Si observamos el código de forma minuciosa podemos observar dos puntos muy interesantes,
el primero es que esta función no es recursiva, y la segunda es que se utiliza una Cola para
controlar el flujo del recorrido.
Los pasos para hacer el recorrido es el siguiente:

1. Se agrega la Raíz a la cola de nodos por visitar


2. Mientras que la cola no este vacía se saca el primer elemento de la cola y continuamos
con el paso 3, Pero; si la cola esta vacía entonces nos vamos al paso 5.
3. Se valida si el elemento sacado de la pila es el que estamos buscando, Si lo es, entonces
hemos terminado, Si no lo es se agregan todos los hijos del nodo a la pila de nodos
pendientes por procesar.
4. Regresamos al paso 2.
5. Terminamos sin un resultado.

Conclusiones
Como hemos observado los arboles son estructuras bastante complejas, tiene una gran
aplicaciones en la ciencia y en la programación convencional. En los últimos años este tipo de
estructuras ha sido utilizadas con mucha frecuencia en la Inteligencia artificial.
En esta publicación hemos visto los puntos vas relevantes a en cuenta a lo que son los arboles
y los principales métodos de búsqueda, sin embargo estamos lejos de cubrir este tema en
profundidad ya que existen muchísimos tipos de operaciones y algoritmos que se pueden
realizar sobre estas estructuras de datos.
Espero que este información te sirve de utilidad y no olvides darle like y recomendar esta
publicación ya que esto me servirá para crear mas y mejor material.
Arbol Binario de Busqueda !!!
CODIGO COMPLETO AQUI !!!
#1 Mensaje por Diabliyo » 06/02/2005 10:25 pm

Hola:

Aqui les dejo mi codigo ( que igualmente se lo pueden bajar de


la seccion de Descargas--> Algoritmos de esta pagina ).

Incluye un Arbol Binario de Busqueda onc las Sig


Caracteristicas:

-Insercion
-Recorridos
-Busquedas
-Alturas
-Nodos
-Podar
---------------> DESCARGALO <----------------
CÓDIGO: SELECCIONAR TODO
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <ctype.h>

struct arbol
{
int dato;
struct arbol *izq;
struct arbol *der;
}*raiz;

enum{ FALSO=0, VERDADERO };

/*PROTOTIPOS*/
void inicializar( void );
int vacio( struct arbol *hoja );
int eshoja( struct arbol *hoja );
struct arbol *insertar( struct arbol *raiz, struct
arbol *hoja, int num );
int busqueda( struct arbol *hoja, int num );
int alturax( struct arbol *hoja, int num );
int alturafull( struct arbol *hoja, int *altura );
void auxaltura( struct arbol *hoja, int *altura, int
cont );
int nodos( struct arbol *hoja );
void auxnodos( struct arbol *hoja, int *cont );
struct arbol *borrarx( struct arbol *hoja, int num
);
struct arbol *podar( struct arbol *hoja );
void preorden( struct arbol *hoja );
void inorden( struct arbol *hoja );
void posorden( struct arbol *hoja );
void menu_recorridos( void );
void menu_busquedas( void );
void menu_alturas( void );
void menu_nodos( void );
void menu_podar( void );

void inicializar( void )


{
raiz= NULL;
}

int vacio( struct arbol *hoja )


{
if( !hoja ) return VERDADERO;
return FALSO;
}

int eshoja( struct arbol *hoja )


{
if( hoja->izq==NULL && hoja->der==NULL )
return VERDADERO;
return FALSO;
}

struct arbol *insertar( struct arbol *raiz, struct


arbol *hoja, int num )
{
if( !hoja )
{
hoja= (struct arbol *) malloc( sizeof
(struct arbol) );
hoja->dato= num;
hoja->izq= NULL;
hoja->der= NULL;
if( !raiz ) return hoja;
else if( num<raiz->dato ) raiz->izq=
hoja;
else raiz->der= hoja;
return hoja;
}
else if( num<hoja->dato )
insertar( hoja, hoja->izq, num );
else insertar( hoja, hoja->der, num );
return raiz;
}

int busqueda( struct arbol *hoja, int num )


{
while( hoja )
{
if( num==hoja->dato ) return VERDADERO;
else
{
if( num<hoja->dato ) hoja= hoja-
>izq;
else hoja= hoja->der;
}
}
return FALSO;
}

int alturax( struct arbol *hoja, int num )


{
int altura=1;

while( hoja )
{
if( num==hoja->dato ) return altura;
else
{
altura++;
if( num<hoja->dato ) hoja= hoja-
>izq;
else hoja= hoja->der;
}
}
return FALSO;
}

int alturafull( struct arbol *hoja, int *altura )


{
auxaltura( hoja, altura, 1 );
return *altura;
}

void auxaltura( struct arbol *hoja, int *altura, int


cont )
{
if( !hoja ) return;

auxaltura( hoja->izq, altura, cont+1 );


auxaltura( hoja->der, altura, cont+1 );
if( (eshoja( hoja ) && cont)>*altura ) *altura=
cont;
}

int nodos( struct arbol *hoja )


{
int nodos=0;
auxnodos( hoja, &nodos );
return nodos;
}

void auxnodos( struct arbol *hoja, int *cont )


{
if( !hoja ) return;

(*cont)++;
auxnodos( hoja->izq, cont );
auxnodos( hoja->der, cont );
}

struct arbol *borrarx( struct arbol *hoja, int num )


{
if( hoja->dato==num )
{
struct arbol *p, *p2;

if( vacio( hoja ) )


{
free( hoja );
hoja= NULL;
return hoja;
}
else if( hoja->izq==NULL )
{
p= hoja->der;
free( hoja );
return p;
}
else if( hoja->der==NULL )
{
p= hoja->izq;
free( hoja );
return p;
}
else
{
p= hoja->der;
p2= hoja->der;
while( p->izq ) p= p->izq;
p->izq= hoja->izq;
free( hoja );
return p2;
}
}
else if( num<hoja->dato )
hoja->izq= borrarx( hoja->izq, num );
else
hoja->der= borrarx( hoja->der, num );
return hoja;
}

struct arbol *podar( struct arbol *hoja )


{
if( !hoja ) return hoja;

podar( hoja->izq );
podar( hoja->der );
free( hoja );
hoja= NULL;
return hoja;
}

/*Recorridos*/

void preorden( struct arbol *hoja )


{
if( !hoja ) return;

printf( "%i ", hoja->dato );


preorden( hoja->izq );
preorden( hoja->der );
}

void inorden( struct arbol *hoja )


{
if( !hoja ) return;

inorden( hoja->izq );
printf( "%i ", hoja->dato );
inorden( hoja->der );
}

void posorden( struct arbol *hoja )


{
if( !hoja ) return;

posorden( hoja->izq );
posorden( hoja->der );
printf( "%i ", hoja->dato );
}

/*Menus del Arbol*/


void menu_recorridos( void )
{
char _op='S';

while( _op!='4' )
{
clrscr();
printf( "1. PreOrden." );
printf( "\n2. InOrden." );
printf( "\n3. PosOrden." );
printf( "\n4. Salir." );
printf( "\n\n:: " );
_op= getch();
switch( _op )
{
case '1':
preorden( raiz );
getch();
break;
case '2':
inorden( raiz );
getch();
break;
case '3':
posorden( raiz );
getch();
break;
}
}
return;
}

void menu_busquedas( void )


{
int val;

printf( "\n\nNumero: " );


scanf( "%i", &val );
if( busqueda( raiz, val ) )
printf( "\n\nEncontrado.." );
else printf( "\n\nError, No se encuentra." );
getch();
}

void menu_alturas( void )


{
char _op='A';
int val, altura;

while( _op!='3' )
{
clrscr();
printf( "1. Altura de Un Nodo \(
Profundidad \). " );
printf( "\n2. Altura de Todo el Arbol."
);
printf( "\n3. Salir." );
printf( "\n\n:: " );
_op= getch();
switch( _op )
{
case '1':
printf( "\n\nNumero: " );
scanf( "%i", &val );
altura= alturax( raiz, val );
if( !altura ) printf(
"\n\nImposible, numero inexistente." );
else printf( "\n\nLa Altura
es: %i", altura );
getch();
break;
case '2':
altura= 0;
printf( "\n\nLa Altura del
Arbol es: %i", alturafull( raiz, &altura ) );
getch();
break;
}
}
return;
}

void menu_nodos( void )


{
printf( "\n\nEl Numero de Nodos es: %i", nodos(
raiz ) );
getch();
}

void menu_podar( void )


{
char _op='A';
int val;

while( _op!='3' )
{
clrscr();
printf( "1. Podar Un Nodos del Arbol." );
printf( "\n2. Podar Todo el Arbol." );
printf( "\n3. Salir." );
_op= getch();
switch( _op )
{
case '1':
printf( "\n\nNumero: " );
scanf( "%i", &val );
raiz= borrarx( raiz, val );
printf( "\n\n.... Borrado
...." );
break;
case '2':
raiz= podar( raiz );
printf( "\n\nArbol Borrado por
Completo." );
getch();
break;
}
}
return;
}

int main()
{
char _op='A';
int val;

inicializar();

while( _op!='S' )
{
clrscr();
printf( "Insertar." );
printf( "\nRecorridos." );
printf( "\nBusquedas." );
printf( "\nAlturas." );
printf( "\nNodos." );
printf( "\nPodar." );
printf( "\nSalir." );
printf( "\n\n:: " );
_op= toupper( getch() );
switch( _op )
{
case 'I':
printf( "\n\nNumero: " );
scanf( "%i", &val );
if( busqueda( raiz, val ) )
{
printf( "\n\nEste numero
ya ha sido insertado." );
getch();
break;
}
raiz= insertar( raiz, raiz,
val );
break;
case 'R':
if( vacio( raiz ) )
{
printf( "\n\nEl Arbol Aun
esta Vacio." );
getch();
break;
}
menu_recorridos();
break;
case 'B':
if( vacio( raiz ) )
{
printf( "\n\nEl Arbol Aun
esta Vacio." );
getch();
break;
}
menu_busquedas();
break;
case 'A':
if( vacio( raiz ) )
{
printf( "\n\nEl Arbol Aun
esta Vacio." );
getch();
break;
}
menu_alturas();
break;
case 'N':
if( vacio( raiz ) )
{
printf( "\n\nEl Arbol Aun
esta Vacio." );
getch();
break;
}
menu_nodos();
break;
case 'P':
if( vacio( raiz ) )
{
printf( "\n\nEl Arbol Aun
esta Vacio." );
getch();
break;
}
menu_podar();
break;
}
}
printf( "\n\nPulsa para salir..." );
getchar();
return 0;
}
byeeeeeee

Hola estoy programando en c++!!


Tengo la clase de arboles binarios
implementada!
Y ahora tengo que hacer una función
externa que compruebe si dos arboles
son iguales. Alguien me puede ayudar con
el codigo??

Gracias!!

Aqui os pongo como tengo la clase arbol!!

Código:

template <class T>


class arbin {
public:
arbin();
arbin(const T & e, const arbin<T> & ai=arbin(), const arbin<T> & ad=arbin());
void Vaciar();
const arbin<T> & Izquierdo() const;
const arbin<T> & Derecho() const;
const T & DatoRaiz() const;
bool Esvacio() const;
void Inorden() const;
void Copiar(const arbin<T> & origen);
arbin<T> &operator=(const arbin <T>& origen);
int Altura() const;

private:
class nodo { //nodo del arbol binario
public:
T info;
arbin<T> izq, der;
nodo (const T & e=T(), const arbin<T> &ni=arbin(), const arbin<T> & nd=arbin()):
info(e), izq(ni), der(nd) {}
};
typedef nodo* nodoptr;
nodoptr raiz;
};

Volver arriba

WhiteSkull Publicado: Martes 26 May 2009 17:57


CoAdmin
Título del mensaje: Re: arboles
binarios

Por lo q se ve, se trata de una práctica con


Registrado: 20 Mar 2009
template?¿?
Mensajes: 3136
Ubicación: y*width+x
http://es.wikipedia.org/wiki/arbol_binario

sólo tienes que hacer una funcion que recorra


nodo por nodo (Preorden o PostOrden) y
compruebe que cada nodo tiene arbol derecho
e izquierdo, de no coincidir con el otro nodo,
que retorne 1, por ejemplo...

Ánimo, si has creado ese código tan complejo


te será muy fácil hacer esa chorrada

Volver arriba

WhiteSkull Publicado: Miércoles 27 May 2009 17:46


CoAdmin
Título del mensaje: Re: arboles
binarios
Registrado: 20 Mar 2009 Los arboles binarios pueden hacerse de mil
Mensajes: 3136 formas, siempre que se respeten los
Ubicación: y*width+x
fundamentos principales: Gestión de Nodos,
cada Nodo alberga un Dato, cada Nodo
apuntará a su Padre y todos los Nodos tienen
uno o ningún hermano, de ahí que sean
binarios 1 o 0. Así de simple, luego hay otros
métodos que usan estructuras más complejas
con el fin de que la búsqueda sea más rápida,
más eficientes, u ocupen memos
memoria. Ejemplo sencillo de C# de un
Arbol Binario, algo más sencillo que lo que
propone Sandra:

Código:

public class ArbolBinario


{

private tArbol[] ArbolB;

private int nodo;

public ArbolBinario(tArbol[] array)


{ // Inicio
ArbolB=array;
this.Nodo = 0;
}
public int Nodo {
get { return this.nodo; }
set { this.nodo = value; }
}
public void Toma(int valor) {
ArbolB[Nodo].Info=valor;
}
public int Devuelve {
get { return ArbolB[Nodo].Info; }
}
public void Izquierdo(int valor) {
// Buscamos un nodo libre
if (ArbolB[Nodo].hIzquierdo == 0) {
int libre = NodoLibre();
ArbolB[libre].Info = valor;
ArbolB[Nodo].hIzquierdo = libre;
} else ArbolB[ArbolB[Nodo].hIzquierdo
}
public void Derecho(int valor) {
if (ArbolB[Nodo].hDerecho == 0) {
int libre = NodoLibre();
ArbolB[libre].Info = valor;
ArbolB[Nodo].hDerecho = libre;
} else ArbolB[ArbolB[Nodo].hDerecho].
}
public int hIzquierdo{
get { return ArbolB[Nodo].hIzquierdo;
}
public int hDerecho {
get { return ArbolB[Nodo].hDerecho; }
}
private int NodoLibre()
{
inti;
for( i = 1; i < ArbolB.Length-1; i++
if ((ArbolB[i].Info == 0) &&
(ArbolB[i].hIzquierdo == 0) &
(ArbolB[i].hDerecho == 0)) br
return i;
}
}
/********************************************
public struct tArbol // Contenido de un nodo
{
public int Info; // Datos variados, quizás
public int hIzquierdo, hDerecho;
};

static void Main(string[] args)


{
tArbol[] Nodo = new tArbol[10];
ArbolBinario Arbol=new ArbolBinario(Nodo)

Arbol.Izquierdo(12);
Arbol.Nodo = Arbol.hIzquierdo;
Arbol.Izquierdo(3);
Arbol.Nodo = Arbol.hIzquierdo;
Arbol.Derecho(55);
Arbol.Izquierdo(50);
Arbol.Toma(10); // Asignamos un valor al

for(int i=0;i<Nodo.Length;i++)
Console.WriteLine("Nodo["+i+"] El der

Console.ReadKey();
}

suerte

void Arbol::Alola(Nodo* a, int n){


if(a != NULL){ // Si el árbol no está vacío
Alola(a->Derecha, n+1);
for(int i = 0; i < n; i++)
cout << " ";
cout << a->dato << endl;
Alola(a->Izquierda, n+1);
}
}

void Arbol::Alola(Nodo* a, int espacios=0) {


if(a != NULL) {
if(a->Izquierda) {
Alola(a->Izquierda, espacios+4);
}
if(a->Derecha) {
Alola(a->Derecha, espacios+4);
}
if (espacios) {
std::cout << std::setw(espacios) << ' ';
}
cout<< a->dato << "\n ";
}
}
Incluye la librería iomanip (para setw) y llama al método con Alola(raiz) y debería funcionar.
EDIT1 Lo único que se me ocurre es que recorras las filas por DFS y vayas imprimiendo.
#include <queue>
#include<iomanip>
#include<cmath>

int Arbol::tamanyo(Nodo *nodo) const {


return (nodo == NULL)? 0 : tamanyo(nodo->Izquierda) + tamanyo(nodo->Derecha) + 1;
}
void Arbol:Alola(Nodo *root){
std::queue<Nodo *> colaNodos;
int totalNodos=tamanyo(root);
int techo=log2(totalNodos+1);
colaNodos.push(root);
int pot=0;
while(colaNodos.size() > 0){
int niveles = colaNodos.size();
while(niveles > 0){
Nodo *nodoAux = colaNodos.front();
colaNodos.pop();
cout<<setw((niveles==pow(2,pot))?pow(2, (techo-pot)):pow(2, (techo-pot+1)));
cout<<nodoAux->dato;
if(nodoAux->Izquierda != NULL) colaNodos.push(nodoAux->Izquierda);
if(nodoAux->Derecha != NULL) colaNodos.push(nodoAux->Derecha);
niveles--;
}
pot++;
cout << endl;
}
}
compartirmejorar esta respuesta
editada el 20 dic. 16 a las 13:29
respondida el 19 dic. 16 a las 15:19

mrcone
343
 Gracias, pero la salida del código no tiene nada que ver con lo que quiero. – akko el 20 dic. 16 a las 3:03
añade un comentario
voto a favor0votar en contra

Con el código que esta en el blog de Martin Cruz, hice una modificación en la función de
mostrar implementando la función gotoxy(), la cual comparta a continuación.
int auxX = 0;//Variable publica.
auxX = 0;//se debe reestablecer a 0 cada vez que se desea llamar la función
mostrarArbol(miArbol,0);

void mostrarArbol(aNodo miArbol, int auxY){//auxY es el nivel del arbol

if(miArbol == NULL){//Arbol vacio nada que mostrar

return;
}

auxX += 5;//variable que permite posicionarse en el eje X

mostrarArbol(miArbol -> izq,auxY+2);//Se para hasta el nodo mas a la izquierda del árbol construye
primero el subarbol izq porque sus valores en X son menores

gotoxy(10+auxX-auxY , 15+auxY);//posiciona el nodo segun sus variables en X y en Y

cout << miArbol -> dato << endl << endl;//Muestra el dato del nodo respectivo

mostrarArbol(miArbol -> der,auxY+2);//Se para hasta el nodo mas a la derecho del árbol
//Se debe tener el cuenta el funcionamiento de la recursividad la cual implementa una pila para almacenar
las instrucciones
}//
compartirmejorar esta respuesta
editada el 19 nov. 17 a las 14:55

Johnny
932211
respondida el 19 nov. 17 a las 3:11

Jorge Pinzon
12
 Gracias Johnny así es como quería que se viera el código y la explicación, es la primera vez que hago un
aporte en este sitio, gracias nuevamente. – Jorge Pinzon el 19 nov. 17 a las 17:18
añade un comentario

lemonde066
 Nuevo Miembro


 Mensajes: 2

o

Como Imprimir Los Nodos De Un Arbol Binario?


« en: Miércoles 9 de Abril de 2008, 17:30 »

como estan amigos. he buscado en internet y en muchos codigos fuente, pero mi duda surge
porque no logro que me ordene los datos en preorden, inorden y postorden?. imprimo los valores
cada vez que los ingreso al arbol para verificar que si estan entrando; pero a la hora de llamar a mi
funcion dependiendo que tipo de orden quiero se queda en overflow; segun he revisado y al
parecer me toma la raiz =NULL. no tengo mucha experiencia como programador y menos en
arboles
utilizo turbo c++ IDE en una pentium IV de 3 ghz.

adjunto mi codigo para que alguien pueda ver lo que yo no.

pd. en el "case" existen opciones que he puesto pero aun no tienen su funcion respeciva.

#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <string.h>

#define NULL 0
int nodo;
int cuenta_nodos=0;
int contador[6];

void menu(void);
void inserta(struct arbol *raiz, int nodo);
void preorden(struct arbol *raiz);
void inorden(struct arbol *raiz);
void postorden(struct arbol *raiz);

struct arbol
{
int dato;
struct arbol *izq;
struct arbol *der;
};
struct arbol *raiz=NULL;

main(void)
{
clrscr();
menu();
getch();
return 0;
}

void menu(void)
{clrscr();
int opcion;
gotoxy(1,30);cout<<("1...ingresar nodo");
gotoxy(1,31);cout<<("2...ordenar en preorden");
gotoxy(1,32);cout<<("3...ordenar en inorden");
gotoxy(1,33);cout<<("4...ordenar en postorden");
gotoxy(1,34);cout<<("5...cuantos nodos tiene el arbol ");
gotoxy(1,35);cout<<("6...cual es el valor maximo ");
gotoxy(1,36);cout<<("7...promedio valor de los nodos");
gotoxy(1,37);cout<<("0...salir");
gotoxy(1,38);cin>>opcion;
switch(opcion)
{ case 1:
{ for (int j=0;j<7;j++)
{ gotoxy(1,1);cout<<("ingresa valor");
gotoxy(18,1);cin>>nodo;
inserta(raiz,nodo);
}
menu(); break;
}
case 2: { preorden(raiz);
getch();
menu(); break;
}
case 3: { inorden(raiz);
menu(); break;
}
case 4: { postorden(raiz);
getch();
menu(); break;
}
case 5: { gotoxy(1,15); cout<<("tiene",cuenta_nodos);
getch();
menu(); break;
}
case 0:
{ break ;}

default:
menu();
}
}
void inserta (arbol *raiz,int nodo)
{
if (raiz==NULL)
{
raiz=(arbol *)malloc(sizeof(arbol*));
raiz->dato=nodo;
cuenta_nodos=cuenta_nodos+1;
contador[cuenta_nodos]=nodo;
raiz->izq=raiz->der=NULL;
gotoxy(15,2); cout<<("la raiz es ",raiz->dato);
gotoxy(20,4); cout<<("el nodo derecho es:", raiz->der);
gotoxy(5,4); cout<<("el nodo izquierdo es:", raiz->izq);
gotoxy(30,1); cout<<("ef",contador);
gotoxy(45,1); cout<<contador[cuenta_nodos];
getch();
}
else
if (raiz->dato < nodo)
{ inserta(raiz->der,nodo);}

else
if (raiz->dato >nodo)
{ inserta (raiz->izq, nodo);}
}

void inorden(arbol *raiz)


{
if(raiz!=NULL)
{
inorden(raiz->izq);
printf("%d",raiz->dato);
inorden(raiz->der);
getch();
}
else
{
cout<<("el arbol no tiene nodos");
}
}

void preorden(arbol *raiz)


{
if(raiz!=NULL)
{
printf("%d ",raiz->dato);
preorden(raiz->izq);
preorden(raiz->der);
}
}

void postorden(arbol *raiz)


{
if(raiz!=NULL)
{
postorden(raiz->izq);
postorden(raiz->der);
printf("%d ",raiz->dato);
}
}
SOLUCIÓN AL EJERCICIO Nº 7 DE ÁRBOLES
BINARIOS

La altura de un árbol T es uno más el máximo de alturas de los subárboles


izquierdo y derecho(La altura de un árbol nulo está indefinida).El código es el
siguiente:
#define MAXIMO(a,b) ((a) < (b)?(b):(a))

int altura(NodoN n,ArbolB T)


{
if(n==NODOB_NULO)
return -1;
else
return 1+MAXIMO(altura(HijoIzqdaB(n,T),T),altura(HijoDrchaB(n,T),T));
}

SOLUCIÓN AL EJERCICIO Nº 1 DE ÁRBOLES


BINARIOS

El código es el siguiente:
int Evalua(NodoB n,ArbolB T)
{
char ident;

EtiquetaArbolB(&c,n,T);
switch(c){
case '+':
return Evalua(HijoIzqdaB(n,T),T)+Evalua(HijoDrchaB(n,T),T);
break;
case '-':
return Evalua(HijoIzqdaB(n,T),T)-Evalua(HijoDrchaB(n,T),T);
break;
case '*':
return Evalua(HijoIzqdaB(n,T),T)*Evalua(HijoDrchaB(n,T),T);
break;
case '/':
return Evalua(HijoIzqdaB(n,T),T)/Evalua(HijoDrchaB(n,T),T);
break;
default:
return valor(c);
}
}

SOLUCIÓN AL EJERCICIO Nº 2 DE ÁRBOLES


BINARIOS

Las soluciones son las siguientes:

A) El árbol correspondiente es el de la siguiente figura:


B)El recorrido en postorden es IBAEDLFCHJKMG.

C)El código solución al tercer apartado es el siguiente:


/*Fichero: comprobar.c */

#include < stdio.h>


#include < stdlib.h>
#include < string.h>

char *preorden="GEAIBMCLDFKJH";
char *inorden="IABEGLDCFMKHJ";
char *postorden;

/*---------------------------------------*/

void post(char *pre,char *in,char *pos,int n)


{
int longIzqda;

if(n!=0){
pos[n-1]=pre[0];
longIzqda=strchr(in,pre[0])-in;
post (pre+1,in,pos,longIzqda);
post (pre+1+longIzqda,in+1+longIzqda,pos+longIzqda,n-1-longIzqda);
}
}

/*----------------------------------------*/

int main(int argc,char *argv[])


{
int aux;

aux=strlen(preorden);
postorden=(char *)malloc(aux*sizeof(char));
if (postorden){
printf("El preorden es: %s\n",preorden);
printf("El inorden es: %s\n",inorden);
post(preorden,inorden,postorden,aux);
postorden[aux]='\0';
printf("El postorden calculado es: %s\n",postorden);
free(postorden);
}
else{
fprintf(stderr,"Error: Sin memoria\n");
return 1;
}

return 0;
}

UCIÓN AL EJERCICIO Nº 3 DE ÁRBOLES


BINARIOS

El código es el siguiente:
/*Fichero: comprobar.c */

#include < pilas.h>


#include < arbolesB.h>

/*---------------------------------------*/

void inordenNR(ArbolB T,void (* EscribirElemento)(void *),int tamano)


{
NodoB nodoActual,aux;
void *et;
Pila p;
int fin;
int faltaHD; /*Indica si falta el hijo derecho*/

p=CrearPila(sizeof(NodoB));
et=malloc(tamano);
if(!et){
.... /*Error:Sin memoria*/
}

aux=NODOB_NULO;
Push(&aux,p);
nodoActual=RaizB(T);
fin=0;
while(!fin){
while(nodoActual!=NODOB_NULO){
Push(&nodoActual,p);
nodoActual=HijoIzqdaB(nodoActual,T);
}
Tope(&nodoActual,p);
Pop(p);
if (nodoActual!=NODOB_NULO){
EtiquetaArbolB(et,nodoActual,T);
(*EscribirElemento)(et);
nodoActual=HijoDrchaB(nodoActual,T);
}
else fin=1;
}

free(et);
DestruirPila(p);
}

SOLUCIÓN AL EJERCICIO Nº 5 DE ÁRBOLES


BINARIOS

El código es el siguiente:

void Refleja(ArbolB T)
{
ArbolB Ti,Td;

if(T!=ARBOLB_VACIO){
Ti=PodarHijoIzqdaB(RaizB(T),T);
Td=PodarHijoDrchaB(RaizB(T),T);
Refleja(Ti);
InsertarHijoDrchaB(RaizB(T),Ti,T);
Refleja(Td);
InsertarHijoIzqdaB(RaizB(T),Td,T);
}
}

SOLUCIÓN AL EJERCICIO Nº 6 DE ÁRBOLES


BINARIOS

El algoritmo es muy sencillo considerando que el número de nodos de un árbol


binario es el número de nodos del hijo a la izquierda más el de su hijo a la
derecha más 1.El código es el siguiente:

int numero(NodoB n,ArbolB T)


{
if (n==NODOB_NULO)
return 0;
else
return 1+numero(HijoIzqdaB(n,T),T)+numero(HijoDrchaB(n,T),T);
}

Para calcular el número de nodos de un árbol T se haría mediante la llamada


numero(RaizB(T),T).

SOLUCIÓN AL EJERCICIO Nº 7 DE ÁRBOLES


BINARIOS
La altura de un árbol T es uno más el máximo de alturas de los subárboles
izquierdo y derecho(La altura de un árbol nulo está indefinida).El código es el
siguiente:
#define MAXIMO(a,b) ((a) < (b)?(b):(a))

int altura(NodoN n,ArbolB T)


{
if(n==NODOB_NULO)
return -1;
else
return 1+MAXIMO(altura(HijoIzqdaB(n,T),T),altura(HijoDrchaB(n,T),T));
}