ARBOLES BINARIOS
BUSQUEDA INSERCIÓN ELIMINAR
2
CONTENIDO 1. Creación del árbol binario en memoria ram 2. Gestión del árbol binario que incluya : a. Inserción de un nodo. b. Borrado de un nodo
Edición y redacción José G. Pérez CI.18.884.212
Cátedra Estructura de Datos II
C. Consulta de información de un nodo.
3. Pasatiempos
Semestre V
4. Ejemplos 5. Webgrafias
Profesora Yakirana Berrios
Universidad Fermín Toro Edo.Lara
3
EDITORIAL Codificación Huffman En 1951, a David Huffman y sus compañeros de clase de la asignatura “Teoría de la Información” se les permitió optar entre la realización de un examen final o la presentación de un trabajo. El profesor Robert. M. Fano asignó las condiciones del trabajo bajo la premisa de encontrar el código binario más eficiente. Huffman, ante la imposibilidad de demostrar qué código era más eficiente, se rindió y empezó a estudiar para el examen final. Mientras estaba en este proceso vino a su mente la idea de usar árboles binarios de frecuencia ordenada y rápidamente probó que éste era el método más eficiente. Con este estudio, Huffman superó a su profesor, quien había trabajado con el inventor de la teoría de la información Claude Shannon con el fin de desarrollar un código similar. Huffman solucionó la mayor parte de los errores en el algoritmo de codificación Shannon-Fano. La solución se basaba en el proceso de construir el árbol de abajo a arriba en vez de al contrario.
David A. Huffman
4
El Programador 1. Creación del árbol binario en memoria RAM Según su definición un árbol binario es una estructura de datos. Normalmente el estudio de las estructura de datos supone que éstos se encuentran almacenados en memoria RAM a no ser que sean muy extensos que haya que colocarlos en otra unidad de almacenamiento por su tamaño. Para nuestros efectos se almacenan en memoria RAM Es por ello, que partiendo de estas declaraciones, se crea una estructura de datos para de esta manera contestar la primera pregunta.
Comentarios hechos por programadores cuando sus programas no funcionan: 1. ¡Qué extraño!… 2. Pues ayer funcionaba. 3. ¿Esto cómo es posible?
Enumeraremos los pasos para crearlo:
I.
Estructura tu árbol binario. Cada árbol binario necesitará una estructura, aunque sólo tenga una variable. Se elige un nombre, y luego se usa typedef para crearlo: typedef struct contacto_dato por ejemplo usaremos CONTACTO_DATO;
4. ¿Se ha actualizado el sistema operativo? 5. Tendrás el ejecutable incorrecto.
CONTACTO_DATO. II.
Se Define la estructura. Incluye dos punteros a la misma estructura: struct contacto_dato { int contacto_ID;
III.
int
6. Vaya, eso es simplemente es una mejora.
contacto_telefono;
CONTACTO_DATO *left, *right;}; Se asigna un puntero hacia esta estructura de datos,
7. Por supuesto, solo tengo que arreglar esos fallitos.
inicializándolo con NULL, para que sea la raíz del árbol: CONTACTO_DATO *contacto = NULL;
8. ¿Todavía no lo he arreglado?
Ejemplo de sintaxis: typedef struct _nodo { int dato; struct _nodo *derecho; struct _nodo *izquierdo; } tipoNodo; typedef tipoNodo *pNodo; typedef tipoNodo *Arbol;
9. Alguien ha tenido que cambiar mi código. 10. Eso es un problema de configuración. ¿Qué programador no ha dicho alguna de estas alguna vez?
5
El Programador Las listas ligadas, las pilas y las colas son estructuras de datos líneales. Un árbol es una estructura de datos no lineal de dos dimensiones, con sus propiedades especiales. Tres nodos contienen dos o más ligas.
2.- Gestión del árbol binario que incluya: a) Inserción de un Nodo. b) Borrado de un Nodo c) Consulta de Información de un Nodo. Según el diccionario la palabra gestión es llevar a cabo diligencias que hacen posible la realización de una operación comercial o de un anhelo cualquiera. Administrar, por otra parte, abarca las ideas de gobernar, disponer dirigir, ordenar u organizar una determinada cosa o situación. Es por ello que como respuesta de la segunda actividad detallaremos el procedimiento para inserción, borrado o consulta de un nodo.
6
El Programador
a) Inserci贸n de un nodo
7
El Programador I. II. III.
Padre = NULL nodo = Raiz Bucle: mientras actual no sea un árbol vacío o hasta que se encuentre el elemento. a. Si el valor del nodo raíz es mayor que el elemento que buscamos, continuaremos la búsqueda en el árbol izquierdo: Padre=nodo, nodo=nodo->izquierdo. b. Si el valor del nodo raíz es menor que el elemento que buscamos, continuaremos la búsqueda en el árbol derecho: Padre=nodo, nodo=nodo->derecho.
IV. V.
Si nodo no es NULL, el elemento está en el árbol, por lo tanto salimos. Si Padre es NULL, el árbol estaba vacío, por lo tanto, el nuevo árbol sólo contendrá el nuevo elemento, que será la raíz del árbol.
VI.
Si el elemento es menor que el Padre, entonces insertamos el nuevo elemento como un nuevo árbol izquierdo de Padre.
VII.
Si el elemento es mayor que el Padre, entonces insertamos el nuevo elemento como un nuevo árbol derecho de Padre.
b) Borrado de un Nodo
Para borrar un elemento también nos basamos en el algoritmo de búsqueda. Si el elemento no está en el árbol no lo podremos borrar. Si está, hay dos casos posibles:
I.
Se trata de un nodo hoja: en ese caso lo borraremos directamente.
8
El Programador
II.
Se trata de un nodo rama: en ese caso no podemos eliminarlo, puesto que perderíamos todos los elementos del árbol de que el nodo actual es padre. En su lugar buscamos el nodo más a la izquierda del subárbol derecho, o el más a la derecha del subárbol izquierdo e intercambiamos sus valores. A continuación eliminamos el nodo hoja.
Necesitamos un puntero auxiliar para conservar una referencia al padre del nodo raíz actual. El valor inicial para ese puntero es NULL. •
Padre = NULL
•
Si el árbol está vacío: el elemento no está en el árbol, por lo tanto salimos sin eliminar ningún elemento.
•
Si el valor del nodo raíz es igual que el del elemento que buscamos, estamos ante uno de los siguientes casos: El nodo raíz es un nodo hoja: Si 'Padre' es NULL, el nodo raíz es el único del árbol, por lo tanto el puntero al árbol debe ser NULL. Si raíz es la rama derecha de 'Padre',
CURIOSIDADES ESTE ES EL PRIMER TWEET DE GOOGLE, SOLO HACE DOS AÑOS APROXIMADAMENTE.
CÓMO NO, UN MENSAJE BINARIO “I’M 01100110 01100101 01100101 01101100 01101001 01101110 01100111 00100000 01101100 01110101 01100011 01101011 01111001 00001010.” QUE SIGNIFICA “I’M FEELING LUCKY.”
hacemos que esa rama apunte a NULL. Si raíz es la rama izquierda de 'Padre', hacemos que esa rama apunte a NULL. Eliminamos el nodo, y salimos. El nodo no es un nodo hoja: Buscamos el 'nodo' más a la izquierda del árbol derecho de raíz o el más a la derecha del árbol izquierdo. Hay que tener en cuenta que
9
El Programador puede que sólo exista uno de esos árboles. Al mismo tiempo, actualizamos 'Padre' para que apunte al padre de 'nodo'. Intercambiamos los elementos de los nodos raíz y 'nodo'. Borramos el nodo 'nodo'. Esto significa volver a (1), ya que puede suceder que 'nodo' no sea un nodo hoja. (Ver ejemplo 3) •
Si el valor del nodo raíz es mayor que el elemento que buscamos, continuaremos la búsqueda en el árbol izquierdo.
•
Si el valor del nodo raíz es menor que el elemento que buscamos, continuaremos la búsqueda en el árbol derecho.
Ejemplo 1: En el árbol de ejemplo, se borrará el nodo hoja 3. 1. Localizamos el nodo a borrar, al tiempo que mantenemos un puntero a 'Padre'. 2. Hacemos que el puntero de 'Padre' que apuntaba a 'nodo', ahora apunte a NULL. 3. Borramos el 'nodo'.
Ejemplo 2: Borrar un nodo rama con intercambio de un nodo hoja.
10
El Programador En el árbol de ejemplo, borrar el nodo 4. 1. Localizamos el nodo a borrar ('raíz'). 2. Buscamos el nodo más a la derecha del árbol izquierdo de 'raíz', en este caso el 3, al tiempo que mantenemos un puntero a 'Padre' a 'nodo'. 3. Intercambiamos los elementos 3 y 4. 4. Hacemos que el puntero de 'Padre' que apuntaba a 'nodo', ahora apunte a NULL. 5. Borramos el 'nodo'.
Ejemplo 3: Borrar un nodo rama con intercambio de un nodo rama. Para este ejemplo usaremos otro árbol. En éste borraremos el elemento 6.
11
El Programador
1. Localizamos el nodo a borrar ('raíz'). 2. Buscamos el nodo más a la izquierda del árbol derecho de 'raíz', en este caso el 12, ya que el árbol derecho no tiene nodos a su izquierda, si optamos por la rama izquierda, estaremos en un caso análogo. Al mismo tiempo que mantenemos un puntero a 'Padre' a 'nodo'. 3. Intercambiamos los elementos 6 y 12. 4. Ahora tenemos que repetir el bucle para el nodo 6 de nuevo, ya que no podemos eliminarlo.
12
El Programador 1. Localizamos de nuevo el nodo a borrar ('raíz'). 2. Buscamos el nodo más a la izquierda del árbol derecho de 'raíz', en este caso el 16, al mismo tiempo que mantenemos un puntero a 'Padre' a 'nodo'. 3. Intercambiamos los elementos 6 y 16. 4. Hacemos que el puntero de 'Padre' que apuntaba a 'nodo', ahora apunte a NULL. 5. Borramos el 'nodo'
Este modo de actuar asegura que el árbol sigue siendo ABB.
c) Consulta de Información de un Nodo. Hay varios parámetros que podemos calcular o medir dentro de un árbol. Algunos de ellos nos darán idea de lo eficientemente que está organizado o el modo en que funciona.
13
El Programador 1) Comprobar si un árbol está vacío. Un árbol está vacío si su raíz es NULL. 2) Calcular el número de nodos. Tenemos dos opciones para hacer esto, una es llevar siempre la cuenta de nodos en el árbol al mismo tiempo que se añaden o eliminan elementos. La otra es, sencillamente, contarlos. Para contar los nodos podemos recurrir a cualquiera de los tres modos de recorrer el árbol: inorden, preorden o postorden, como acción sencillamente incrementamos el contador.
3) Comprobar si el nodo es hoja. Esto es muy sencillo, basta con comprobar si tanto el árbol izquierdo como el derecho están vacíos. Si ambos lo están, se trata de un nodo hoja. 4) Calcular la altura de un nodo. No hay un modo directo de hacer esto, ya que no nos es
Un hombre está haciendo un vuelo en un globo aerostático. Se extravía y decide descender y preguntar a alguien. Baja a unos 10 metros del suelo y pregunta a una persona que pasaba por allí: - Por favor, ¿puede decirme dónde estoy? - Pues mire, está usted en un globo aerostático, a unos 10 metros del suelo. - Usted es informático, ¿verdad? - Sí, ¿cómo lo sabe? - Porque me ha dado una respuesta técnicamente correcta, pero que no me soluciona nada. - Y usted es usuario, ¿verdad? - Pues sí, ¿cómo lo sabe?
posible recorrer el árbol en la dirección de la raíz. De modo que tendremos que recurrir a otra técnica para calcular la altura. Lo que haremos es buscar el elemento del nodo de que queremos averiguar la altura. Cada vez que avancemos un nodo incrementamos la variable que contendrá la altura del nodo.
- Porque está igual de perdido que antes, pero ahora me echa la culpa a mí.
14
El Programador Empezamos con el nodo raíz apuntando a Raíz, y la 'Altura' igual a cero. Si el valor del nodo raíz es igual que el del elemento que buscamos, terminamos la búsqueda y el valor de la altura es 'Altura'. Incrementamos 'Altura'. Si el valor del nodo raíz es mayor que el elemento que buscamos, continuaremos la búsqueda en el árbol izquierdo. Si el valor del nodo raíz es menor que el elemento que buscamos, continuaremos la búsqueda en el árbol derecho.
5) Calcular la altura de un árbol. La altura del árbol es la altura del nodo de mayor altura. Para buscar este valor tendremos que recorrer todo el árbol, de nuevo es indiferente el tipo de recorrido que hagamos, cada vez que cambiemos de nivel incrementamos la variable que contiene la altura del nodo actual, cuando lleguemos a un nodo hoja compararemos su altura
con
la
variable
que
contiene la altura del árbol si es mayor, actualizamos la altura del árbol. Iniciamos un recorrido del árbol en postorden, con la variable de altura igual a cero. Cada vez que empecemos a recorrer una nueva rama, incrementamos la altura para ese nodo.
15
El Programador Después de procesar las dos ramas, verificamos si la altura del nodo es mayor que la variable que almacena la altura actual del árbol, si es así, actualizamos esa variable. Una vez realizado la teoría busca 2 o 3 ejercicios donde aplique lo anterior (Inserción de un Nodo, Borrado de un Nodo, Consulta de Información de un Nodo.
CURIOSIDADES SABES CUANTOS LENGUAJES DE PROGRAMACIÓN EXISTEN? SE HAN REGISTRADO UN TOTAL DE 1150 LENGUAJES DIFERENTES!
16
El Programador
17
El Programador
18
El Programador 1er Ejemplo Inserción de un nodo. void Insertar(Lista *lista, int v) { pNodo nuevo, anterior;
/* Crear un nodo nuevo */ nuevo = (pNodo)malloc(sizeof(tipoNodo)); nuevo->valor = v;
/* Si la lista está vacía */ if(ListaVacia(*lista) || (*lista)->valor > v) { /* Añadimos la lista a continuación del nuevo nodo */ nuevo->siguiente = *lista; /* Ahora, el comienzo de nuestra lista es en nuevo nodo */ *lista = nuevo; } else { /* Buscar el nodo de valor menor a v */ anterior = *lista; /* Avanzamos hasta el último elemento o hasta que el siguiente tenga un valor mayor que v */ while(anterior->siguiente && anterior->siguiente->valor <= v) anterior = anterior->siguiente; /* Insertamos el nuevo nodo después del nodo anterior */ nuevo->siguiente = anterior->siguiente; anterior->siguiente = nuevo;
19
El Programador
2do Ejemplo Borrado de un nodo. void Borrar(Lista *lista, int v) { pNodo anterior, nodo;
nodo = *lista; anterior = NULL; while(nodo && nodo->valor < v) { anterior = nodo; nodo = nodo->siguiente; } if(!nodo || nodo->valor != v) return; else { /* Borrar el nodo */ if(!anterior) /* Primer elemento */ *lista = nodo->siguiente; else /* un elemento cualquiera */ anterior->siguiente = nodo->siguiente; free(nodo); } }
20
El Programador
21
El Programador 3er Ejemplo de Consulta de Información de un Nodo. #include <stdlib.h> #include <stdio.h> #define TRUE 1 #define FALSE 0
/* Estructuras y tipos */ typedef struct _nodo { int dato; struct _nodo *derecho; struct _nodo *izquierdo; } tipoNodo; typedef tipoNodo *pNodo; typedef tipoNodo *Arbol;
/* Funciones con árboles: */ /* Insertar en árbol ordenado: */ void Insertar(Arbol *a, int dat);
/* Borrar un elemento: */ void Borrar(Arbol *a, int dat);
/* Función de búsqueda: */ int Buscar(Arbol a, int dat);
/* Comprobar si el árbol está vacío: */ int Vacio(Arbol r);
/* Comprobar si es un nodo hoja: */ int EsHoja(pNodo r);
/* Contar número de nodos: */ int NumeroNodos(Arbol a, int* c);
/* Calcular la altura de un árbol: */ int AlturaArbol(Arbol a, int* altura);
/* Calcular altura de un dato: */ int Altura(Arbol a, int dat);
/* Aplicar una función a cada elemento del árbol: */ void InOrden(Arbol, void (*func)(int*)); void PreOrden(Arbol, void (*func)(int*));
22
El Programador void PostOrden(Arbol, void (*func)(int*));
/* Funciones auxiliares: */ void Podar(Arbol *a); void auxContador(Arbol a, int*); void auxAltura(Arbol a, int, int*); void Mostrar(int *d);
/* Programa de ejemplo */ int main() { Arbol ArbolInt=NULL; int altura; int nnodos;
/* Inserci贸n de nodos en 谩rbol: */ Insertar(&ArbolInt, 10); Insertar(&ArbolInt, 5); Insertar(&ArbolInt, 12); Insertar(&ArbolInt, 4); Insertar(&ArbolInt, 7); Insertar(&ArbolInt, 3); Insertar(&ArbolInt, 6); Insertar(&ArbolInt, 9); Insertar(&ArbolInt, 8); Insertar(&ArbolInt, 11); Insertar(&ArbolInt, 14); Insertar(&ArbolInt, 13); Insertar(&ArbolInt, 2); Insertar(&ArbolInt, 1); Insertar(&ArbolInt, 15); Insertar(&ArbolInt, 10); Insertar(&ArbolInt, 17); Insertar(&ArbolInt, 18); Insertar(&ArbolInt, 16); printf("Altura de arbol %d\n", AlturaArbol(ArbolInt, &altura));
23
El Programador /* Mostrar el รกrbol en tres ordenes distintos: */ printf("InOrden: "); InOrden(ArbolInt, Mostrar); printf("\n"); printf("PreOrden: "); PreOrden(ArbolInt, Mostrar); printf("\n"); printf("PostOrden: "); PostOrden(ArbolInt, Mostrar); printf("\n");
/* Borraremos algunos elementos: */ printf("N nodos: %d\n", NumeroNodos(ArbolInt, &nnodos)); Borrar(&ArbolInt, 5); printf("Borrar 5: "); InOrden(ArbolInt, Mostrar); printf("\n"); Borrar(&ArbolInt, 8); printf("Borrar 8: "); InOrden(ArbolInt, Mostrar); printf("\n"); Borrar(&ArbolInt, 15); printf("Borrar 15: "); InOrden(ArbolInt, Mostrar); printf("\n"); Borrar(&ArbolInt, 245); printf("Borrar 245: "); InOrden(ArbolInt, Mostrar); printf("\n"); Borrar(&ArbolInt, 4); printf("Borrar 4: "); InOrden(ArbolInt, Mostrar); printf("\n"); Borrar(&ArbolInt, 17); printf("Borrar 17: "); InOrden(ArbolInt, Mostrar); printf("\n");
24
El Programador /* Veamos algunos parรกmetros */ printf("N nodos: %d\n", NumeroNodos(ArbolInt, &nnodos)); printf("Altura de 1 %d\n", Altura(ArbolInt, 1)); printf("Altura de 10 %d\n", Altura(ArbolInt, 10)); printf("Altura de arbol %d\n", AlturaArbol(ArbolInt, &altura));
/* Liberar memoria asociada al รกrbol: */ Podar(&ArbolInt); system("PAUSE"); return 0; }
/* Poda: borrar todos los nodos a partir de uno, incluido */ void Podar(Arbol *a) {
/* Algoritmo recursivo, recorrido en postorden */ if(*a) { Podar(&(*a)->izquierdo); /* Podar izquierdo */ Podar(&(*a)->derecho); /* Podar derecho */ free(*a); /* Eliminar nodo */ *a = NULL; } }
/* Insertar un dato en el รกrbol ABB */ void Insertar(Arbol *a, int dat) { pNodo padre = NULL; pNodo actual = *a;
/* Buscar el dato en el รกrbol, manteniendo un puntero al nodo padre */ while(!Vacio(actual) && dat != actual->dato) { padre = actual; if(dat < actual->dato) actual = actual->izquierdo; else if(dat > actual->dato) actual = actual->derecho; }
25
El Programador /* Si se ha encontrado el elemento, regresar sin insertar */ if(!Vacio(actual)) return;
/* Si padre es NULL, entonces el árbol estaba vacío, el nuevo nodo será el nodo raiz */ if(Vacio(padre)) { *a = (Arbol)malloc(sizeof(tipoNodo)); (*a)->dato = dat; (*a)->izquierdo = (*a)->derecho = NULL; }
/* Si el dato es menor que el que contiene el nodo padre, lo insertamos en la rama izquierda */ else if(dat < padre->dato) { actual = (Arbol)malloc(sizeof(tipoNodo)); padre->izquierdo = actual; actual->dato = dat; actual->izquierdo = actual->derecho = NULL; }
/* Si el dato es mayor que el que contiene el nodo padre, lo insertamos en la rama derecha */ else if(dat > padre->dato) { actual = (Arbol)malloc(sizeof(tipoNodo)); padre->derecho = actual; actual->dato = dat; actual->izquierdo = actual->derecho = NULL; } }
/* Eliminar un elemento de un árbol ABB */ void Borrar(Arbol *a, int dat) { pNodo padre = NULL; pNodo actual; pNodo nodo; int aux; actual = *a;
/* Mientras sea posible que el valor esté en el árbol */ while(!Vacio(actual)) {
26
El Programador if(dat == actual->dato) { /* Si el valor está en el nodo actual */ if(EsHoja(actual)) { /* Y si además 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; free(actual); /* Borrar el nodo */ actual = NULL; return; } else { /* Si el valor está en el nodo actual, pero no es hoja */ padre = actual;
/* Buscar nodo más izquierdo de rama derecha */ if(actual->derecho) { nodo = actual->derecho; while(nodo->izquierdo) { padre = nodo; nodo = nodo->izquierdo; } }
/* O buscar nodo más 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 sólo se eliminan nodos hoja. */ aux = actual->dato; actual->dato = nodo->dato; nodo->dato = aux; actual = nodo; } }
27
El Programador else { /* Todavía no hemos encontrado el valor, seguir buscándolo */ padre = actual; if(dat > actual->dato) actual = actual->derecho; else if(dat < actual->dato) actual = actual->izquierdo; } } }
/* Recorrido de árbol en inorden, aplicamos la función func, que tiene el prototipo: void func(int*); */ void InOrden(Arbol a, void (*func)(int*)) { if(a->izquierdo) InOrden(a->izquierdo, func); func(&(a->dato)); if(a->derecho) InOrden(a->derecho, func); }
/* Recorrido de árbol en preorden, aplicamos la función func, que tiene el prototipo: void func(int*); */ void PreOrden(Arbol a, void (*func)(int*)) { func(&a->dato); if(a->izquierdo) PreOrden(a->izquierdo, func); if(a->derecho) PreOrden(a->derecho, func); }
/* Recorrido de árbol en postorden, aplicamos la función func, que tiene el prototipo: void func(int*); */ void PostOrden(Arbol a, void (*func)(int*)) { if(a->izquierdo) PostOrden(a->izquierdo, func); if(a->derecho) PostOrden(a->derecho, func);
28
El Programador func(&a->dato); }
/* Buscar un valor en el árbol */ int Buscar(Arbol a, int dat) { pNodo actual = a;
/* Todavía puede aparecer, ya que quedan nodos por mirar */ while(!Vacio(actual)) { if(dat == actual->dato) return TRUE; /* dato encontrado */ else if(dat < actual->dato) actual = actual->izquierdo; /* Seguir */ else if(dat > actual->dato) actual = actual->derecho; } return FALSE; /* No está en árbol */ }
/* Calcular la altura del nodo que contiene el dato dat */ int Altura(Arbol a, int dat) { int altura = 0; pNodo actual = a;
/* Todavía puede aparecer, ya que quedan nodos por mirar */ while(!Vacio(actual)) { if(dat == actual->dato) return altura; /* encontrado: devolver altura */ else { altura++; /* Incrementamos la altura, seguimos buscando */ if(dat < actual->dato) actual = actual->izquierdo; else if(dat > actual->dato) actual = actual->derecho; } } return -1; /* No está en árbol, devolver -1 */ }
/* Contar el número de nodos */ int NumeroNodos(Arbol a, int *contador) {
29
El Programador *contador = 0; auxContador(a, contador); /* Función auxiliar */ return *contador; }
/* Función auxiliar para contar nodos. Función recursiva de recorrido en preorden, el proceso es aumentar el contador */ void auxContador(Arbol nodo, int *c) { (*c)++; /* Otro nodo */
/* Continuar recorrido */ if(nodo->izquierdo) auxContador(nodo->izquierdo, c); if(nodo->derecho) auxContador(nodo->derecho, c); }
/* Calcular la altura del árbol, que es la altura del nodo de mayor altura. */ int AlturaArbol(Arbol a, int *altura) { *altura = 0; auxAltura(a, 0, altura); /* Función auxiliar */ return *altura; }
/* Función auxiliar para calcular altura. Función recursiva de recorrido en postorden, el proceso es actualizar la altura sólo en nodos hojas de mayor altura de la máxima actual */ void auxAltura(pNodo nodo, int a, int *altura) {
/* Recorrido postorden */ if(nodo->izquierdo) auxAltura(nodo->izquierdo, a+1, altura); if(nodo->derecho) auxAltura(nodo->derecho, a+1, altura);
/* 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; }
30
El Programador /* Comprobar si un árbol es vacío */ int Vacio(Arbol r) { return r==NULL; }
/* Comprobar si un nodo es hoja */ int EsHoja(pNodo r) { return !r->derecho && !r->izquierdo; }
/* Función de prueba para recorridos del árbol */ void Mostrar(int *d) { printf("%d, ", *d);
31
El Programador
32
El Programador 4to Ejemplo que involucre todos los ejemplos anteriores. #include <stdlib.h> #include <stdio.h>
typedef struct _nodo { int valor; struct _nodo *siguiente; } tipoNodo;
typedef tipoNodo *pNodo; typedef tipoNodo *Lista;
/* Funciones con listas: */ void Insertar(Lista *l, int v); void Borrar(Lista *l, int v);
int ListaVacia(Lista l);
void BorrarLista(Lista *); void MostrarLista(Lista l);
int main() { Lista lista = NULL;
33
El Programador pNodo p;
Insertar(&lista, 20); Insertar(&lista, 10); Insertar(&lista, 40); Insertar(&lista, 30);
MostrarLista(lista);
Borrar(&lista, 10); Borrar(&lista, 15); Borrar(&lista, 45); Borrar(&lista, 30); Borrar(&lista, 40);
MostrarLista(lista);
BorrarLista(&lista);
return 0; }
void Insertar(Lista *lista, int v) { pNodo nuevo, anterior;
34
El Programador
/* Crear un nodo nuevo */ nuevo = (pNodo)malloc(sizeof(tipoNodo)); nuevo->valor = v;
/* Si la lista está vacía */ if(ListaVacia(*lista) || (*lista)->valor > v) { /* Añadimos la lista a continuación del nuevo nodo */ nuevo->siguiente = *lista; /* Ahora, el comienzo de nuestra lista es en nuevo nodo */ *lista = nuevo; } else { /* Buscar el nodo de valor menor a v */ anterior = *lista; /* Avanzamos hasta el último elemento o hasta que el siguiente tenga un valor mayor que v */ while(anterior->siguiente && anterior->siguiente->valor <= v) anterior = anterior->siguiente; /* Insertamos el nuevo nodo después del nodo anterior */ nuevo->siguiente = anterior->siguiente; anterior->siguiente = nuevo; } }
35
El Programador void Borrar(Lista *lista, int v) { pNodo anterior, nodo;
nodo = *lista; anterior = NULL; while(nodo && nodo->valor < v) { anterior = nodo; nodo = nodo->siguiente; } if(!nodo || nodo->valor != v) return; else { /* Borrar el nodo */ if(!anterior) /* Primer elemento */ *lista = nodo->siguiente; else /* un elemento cualquiera */ anterior->siguiente = nodo->siguiente; free(nodo); } }
int ListaVacia(Lista lista) { return (lista == NULL); }
void BorrarLista(Lista *lista) {
36
El Programador pNodo nodo;
while(*lista) { nodo = *lista; *lista = nodo->siguiente; free(nodo); } }
void MostrarLista(Lista lista) { pNodo nodo = lista;
if(ListaVacia(lista)) printf("Lista vacĂa\n"); else { while(nodo) { printf("%d -> ", nodo->valor); nodo = nodo->siguiente; } print("\n"); } }
37
El Programador
RECURSO
NOMBRE
URL
Imagen
Programadores
Imagen
Publicidad
Consulta
Estructuras
http://4.bp.blogspot.com/jBE6oeCqEnM/UWhEGVcPV4I/AAAAAAAAA LQ/6BiIxv86Uc/s1600/Chiste+programacion.png http://www.monografias.com/trabajos94/fil osofia-del-sistema-sap/img4.png http://www.algoritmia.net/articles.php?id= 17
USO revista
FECHA 19-may
revista 19-may
revista
22-may
38
El Programador