Sie sind auf Seite 1von 27

Arboles

1.- Grafique el rbol que contiene el cdigo de Huffman y complete la tabla dadas las siguientes frecuencias.
Letra
Frecuencia
Cdigo de Huffman
A

18

20

32

b) Codificar las cadenas:


1)AAEIOUE
2)UAUAEI
c) Decodificar las cadenas de bits:
1)0000100100010000001
2)1010010010000010001
Solucin:
Un algoritmo para construir arboles de Huffman consiste en lo siguiente:
Definimos un conjunto de nodos, en donde cada nodo representa las letra como un nodo de un rbol, etiquetamos las
frecuencias definidas para cada letra, tal y como muestra la siguiente figura:

Empezamos con las dos letras de menor frecuencia, estas se unen y crean un nuevo smbolo, la frecuencia del nuevo
nodo es la suma de los dos anteriores, agregamos el nuevo smbolo al conjunto de las letras. Observe que el grupo de
letras se vuelve mas pequeo. Asumiremos que el elemento con menor frecuencia ira siempre a la izquierda. El rbol
formado se muestra a continuacin.

Hacemos esto hasta que no queden nodos en el conjunto.

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Para concluir, en este caso, vamos a marcar los hijos izquierdos con el numero uno y los derechos con el cero. Podemos
omitir las etiquetas de las frecuencias . El rbol de Huffman resultante se presenta a continuacin:

Los cdigos sern los siguientes:


A: 000 E: 01
I:1
O:0011 U:0010
Codificar las cadenas:
1)AAEIOUE=0000000110011001001
Decodificar las cadenas de bits: 1)0000100100010000001:AEEAIAAI

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

2)UAUAEI=00100000010000011
2)1010010010000010001:IEUEAU

2- Dado el siguiente rbol binario completo, conviertalo en un rbol parcialmente ordenado. En la raz debe estar el
mayor de todos.

Solucin:
Recordemos la definicin de un rbol parcialmente ordenado: Un rbol parcialmente ordenado tiene dos principales
caractersticas:
- Es un rbol binario completo, es decir que todos sus niveles estn completos a excepcin del ultimo nivel en donde
las hojas van a apareciendo seguidas de izquierda a derecha.
- Tiene definida alguna propiedad de orden, por ejemplo entre raz e hijos, la raz contiene el menor de todos.
El rbol presentado en el problema es un rbol binario completo, lo que debemos hacer es ajustar los nodos del rbol
de tal forma que se cumpla la propiedad de orden, en este caso en la raz debe estar el mayor de todos. Para facilitar la
explicacin de la resolucin del problema vamos a etiquetar los nodos del rbol:

Empezaremos desde el penltimo nivel del rbol(nivel dos) iremos verificando si el valor de la raz de cada subarbol es
mayor que los valores de sus hijos. Por ejemplo el subarbol con raz en el nodo 7 almacena el valor 63, verificamos con
los nodos hijos: 63>83? falso, debemos intercambiar el valor de los nodos. Ahora la raz almacena el valor de 83,
volvemos a verificar el valor de la nueva raz con los nodos hijos: 83>63?verdadero, 83>73?, tambin es verdadero.
Hacemos esto para todas las races en ese nivel, teniendo lo siguiente:

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Ahora ajustamos desde el nivel 1. Hagamos el anlisis para el subarbol que tiene por raz el nodo 2, que almacena el
valor 47. 47>61? falso, intercambiamos los valores. Ahora el nodo 2 almacena el valor 61, y el nodo 4 el valor 47.
Luego volvemos a verificar el valor de la nueva raz con los nodos hijos: 61>47?verdadero, 61>55?, tambin es
verdadero. Hacemos esto para la raz restante en ese nivel, teniendo lo siguiente:

En este caso en el nivel 0 no es necesario ajustar porque es claro notar que el valor almacenado en la raz, el numero
92, es mayor que sus hijos( 61 y 83). Observe que aun no hemos terminado de resolver el problema, debemos seguir
ajustando, nuevamente desde el penltimo nivel,obteniendo lo siguiente:

Este es el rbol resultante observe que se cumple la propiedad de orden que nos solicitan en el problema.

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

En la tabla proporcionada a continuacin se encuentran las frecuencias aproximadas de las 9 letras mas frecuentes
en el idioma castellano. Construya un rbol de Huffman considerando que:
- En el rbol binario, la rama izquierda se codifica con cero y la derecha con uno.
- Se debe poner siempre a la izquierda al elemento con menor frecuencia, el momento de unir dos smbolos. Si
coinciden en frecuencia se orden alfabticamente.
Letra Frecuencia
E

15

14

11

10

T
4
En base al cdigo construido decodifique la siguiente cadena:
01101100001101011111 0111111110100100111
Solucin:
Antes de empezar a resolver el problema tenemos que tener muy claro que para este caso el texto detalla
explcitamente como debe ser construido el rbol de Huffman, en donde codificaremos los subrboles izquierdos con
el cero y los subrboles derechos con el uno. Considere tambin que el elemento de menor frecuencia va siempre a la
izquierda. Con estas consideraciones ahora procederemos a aplicar el algoritmo que ya conocemos para resolver este
tipo de ejercicios.
Definimos un conjunto de elementos, en donde cada elemento del mismo representa un nodo de un rbol que
almacena una letra con su respectiva frecuencia.

Seleccionamos las dos letras de menor frecuencia, estas se unen y crean un nuevo smbolo, la frecuencia del nuevo
nodo es la suma de los dos anteriores, agregamos el nuevo smbolo al conjunto de las letras. En un principio nuestro
rbol de Huffman estar conformado por los dos nodos de menor frecuencia previamente seleccionados.

Continuamos con este mismo procedimiento hasta que ya no queden nodos por seleccionar.

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Observe que en el proceso se forman varios arboles binarios.

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

El rbol resultante es el que se muestra a continuacin, observe que se cumplen estrictamente las indicaciones del
texto.

Los cdigos obtenidos se detallan a continuacin:


E: 00
A: 111
S: 100
O: 101
R: 010
T: 0110
D: 0111
I: 1100
N: 1101
El significado de la cadena 011011000011010111111 0111111110100100111 es TIENDA DANESA

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

4.- El profesor Gig A. Byte necesita almacenar texto formado con los caracteres A,B,C,D,E que ocurren con las
siguientes frecuencias:
Letra
Frecuencia
A

E
8
El profesor Byte sugiere usar los cdigos de longitud variable:
Carcter

Cdigo

00

01

10

E
0
Los cuales, asegura, almacenan texto en menos espacio que el usado por un cogido Huffman optimo Esta en lo
correcto el profesor? Explique su respuesta.
El problema se resume en lo siguiente, El profesor Gig A. Byte le presenta a usted una opcin alternativa para codificar
letras. El argumento principal que el profesor usa para justificar que su solucin es optima consiste en que los cdigos
que el proponen ocupan menos espacio que un cdigo de Huffman optimo. A usted se le pregunta si la tesis del
profesor Byte es correcta.
Sabemos muy bien que cuando buscamos codificar un conjunto de caracteres, siempre queremos que los caracteres
con mayor frecuencia ocupen un menor espacio, y los caracteres de menor frecuencia ocupen mayor espacio. A simple
vista el modelo propuesto por el profesor Byte cumple esta condicin. Pero cuando proponemos un cdigo para
representar un carcter debemos asegurarnos de un detalle muy importante,evitar la ambigedad. El cdigo
propuesto es ambiguo y confuso. Por ejemplo la cadena 00 podra significar el carcter B o tambin la palabra EE. As
existe un sin numero de cadenas que podran representar varios significados. Por conclusin el cdigo propuesto no es
correcto.

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

5.- Dado los siguientes nmeros enteros: 17,9,26,12,11,7,30,20,21,10


a) Dibuje el rbol binario de bsqueda que resulta de la insercin de estos datos en el orden indicado.
b) Usando el rbol binario del literal anterior, dibuje el estado en que queda el rbol despus de eliminar el
nodo con clave 17.
Solucion:
a) Recuerde que en un Arbol Binario de Busqueda todos los nodos que conforman el arbol tienen cero, uno o dos hijos.
Pero la caracteristica mas importante es que dado un nodo: todos los nodos del subarbol izquierdo tienen una clave
menor que la clave de la raiz. Todos los nodos del subarbol derecho tienen una clave mayor que la clave de la raiz.
Ahora vamos a construir un Arbol Binario de Busqueda con el conjunto que se nos a proporcionado. El primer
elemento del arbol es el 17.

Ahora tenemos que insertar el 9. Como el 9 es menor que el 17 entonces este debe ubicarse en el subarbol izquierdo.

El siguiente elemento es el 26. El numero 26 es mayor que el 17 entonces se debe ubicar en el subarbol derecho.

Ahora tenemos que ingresar el numero 12. El 12 es menor que la raiz 17, entonces debe ubicarse en el subarbol
izquierdo. Este subarbol tiene como raiz el elemento 9. El 12 es mayor que la raiz, entonces debera anexarse en el
subarbol derecho.

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

El elemento que sigue es el 11. Este numero es menor que la raiz 17, esto supone que se debe insertar en el subarbol
izquierdo. Ahora vemos que el once es mayor que la raiz 9 entonces debe ir en el subarbol derecho. El 11 es menor
que la raiz 12 entonces debera ubicarse en la izquierda de dicho nodo.

Seguimos con este procedimiento hasta que ya no queden elementos para insertar.

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

El arbol resultante es el que se muestra a continuacin, observe que siempre se conservan las caracteristicas propias
de un Arbol Binario de Busqueda.

b) Para eliminar un nodo p de un Arbol Binario de Busqueda, primero localizamos la ubicacion de dicho nodo en el
arbol. Para este caso en particular, el nodo a eliminar es la raiz del arbol. Para eliminar la raiz, debemos buscar un nodo
k que sea el mayor de las claves menores.

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Intercambiamos la clave del nodo p con el nodo k. Eliminamos el nodo k.

Ya que el nodo k tiene un solo nodo hijo, basta con intercambiar estas claves. La clave 17 debe bajar hasta que sea un
nodo hoja del arbol.

Por ultimo simplemente se remueve el nodo hoja con la clave 17, el estado final del arbol se muestra a continuacin.

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Se quiere enviar por internet la siguiente imagen (cada color de pixel representado por un nmero entero de 1 byte
de tamao) usando la menor cantidad de bits. Conteste las siguientes preguntas:
0
0
15
25
30
30
25
15
0
0

0
15
25
25
30
30
25
25
15
0

30
30
30
30
30
30
30
30
30
30

0
15
25
25
30
30
25
25
15
0

0
0
15
25
30
30
25
15
0
0

a) Qe tcnica podra utilizar para comprimir la informacin de esta imagen?


b) De la tcnica seleccionada, describa como se calcularan los valores de sus parmetros en base a los datos del
problema.
c) Que porcentaje de reduccin de bits a enviar puede lograr al aplicar la tcnica seleccionada por usted,
justifique su clculo?
d) Qu otro mecanismo cree usted que puede usarse para reducir an ms la cantidad de bits a enviar?
a) Podemos usar un arbol de Huffman, en donde cada nodo del arbol va a representar un color, el arbol lo vamos a
construir en funcion de las frecuencias de cada color en la imagen. De esta forma al enviar la imagen por ejemplo el
numero entero 30 que representa a un color en particular, se enviara con un codigo que ocupe un menor tamao.
b) Las frecuencias serian:
Numero Frecuencia
0

12

15

25

12

30

18

Seguimos el mismo procedimiento que ya conocemos para formar un arbol de Huffman obteniendo lo siguiente:

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Color

Cdigo

00

15

01

25

10

30

11

c)Podemos ver la imagen como una matriz de 10 filas con 5 columnas, en cada celda hay un numero entero que
representa 8 bits, como tenemos 50 celdas la imagen tendra un tamao de 50x8 bits. Aplicando el mecanismo que
hemos descrito, cada numero representara 2 bits, entonces en total seria 50x2 bits.
d) Observando bien la imagen podemos notar que a partir de la fila 5. la imagen se refleja. Es decir la fila 6 es la misma
que la fila 5, la fila 7 es igual que la fila 4, la fila 3 es la misma que la fila 8, la fila 2 es igual que la fila 9 y por ultimo la
ultima fila es la misma que la primera. Podemos usar un mecanismo para enviar la mitad de la imagen y que esta se
refleje con respecto a la fila cinco. Ademas de esto tambien podemos asegurarnos que en el momento de construir el
arbol de Huffman para esta imagen, el arbol debe mantenerse siempre equilibrado, esto hace que los codigos
generados ocupen menor espacio.
Escriba un funcin llamada int SumarArbol que, dado un rbol binario retorne la suma de todos los valores de
sus claves.
En esta funcin nos piden que sumemos todos los valores almacenados en el campo key del TDA NodeTree,
resolveremos esto de forma recursiva. Lo primero que vamos a verificar es que la referencia del nodo que viene por
parmetro es valida. Luego de esto vamos a definir el caso base y las llamadas recursivas. Imaginemos que tenemos un
simple rbol de una raz y tan solo dos hijos, estos dos hijos son nodos hojas de ese rbol, nuestra funcin debera
sumar la clave de la hoja izquierda con la clave de la hoja derecha y con la clave de la raz.
Ahora pensemos en un rbol mas extenso, el problema se resuelve de la misma forma, sumar las claves del subarbol
izquierdo con las claves del subarbol derecho y la clave de la raz. Es decir el problema de sumar las claves del subarbol
izquierdo o derecho es un problema del mismo tipo que el problema original de aqu la naturaleza recursiva de esta
implementacin.
El caso base o fin de la recursion sera cuando tengamos problemas tan pequeos que su solucin es simple, esto sera
cuando lleguemos a un nodo hoja, en donde retornaremos la clave que almacena dicho nodo. Las llamadas recursivas
empiezan cuando el rbol que estemos tratando no sea una hoja, para ese caso llamaremos a la funcin de nuevo
envindole el subarbol izquierdo sumado con otra llamada en donde enviamos el subarbol derecho y esto a su vez
sumado con el contenido de la clave de la raz.
La siguiente solucin resuelve el problema planteado, se recomienda que haga una prueba de escritorio para que se
asegure que todo funciona como debera.
int sumarClaves(Tree A) {
if (A != NULL) {
if ( A->left == NULL && A->right == NULL) {
return integerGet(A->key);
} else {
return sumarClaves(A->left) + sumarClaves(A->right) + integerGet(A->key);
}
}else{
return 0;
}
}

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Escriba una funcin recursiva espejo que para un rbol binario retorne el rbol invertido, como se muestra en la
figura:

Solucion:
El problema simplemente consiste en intercambiar los punteros Left y Right de un rbol. Esta operacin se la har
tantas veces como races existan en el rbol. El cdigo a continuacin resuelve el problema descrito, observe que una
vez que se realiza la operacin de intercambio se vuelve a llamar a la funcin envindole las referencias a los
subarboles izquierdo y derecho, el final de llamadas sera cuando encontremos un nodo hoja, en donde simplemente
no se debe hacer nada.
int esHoja(NodeTree*nodo){
if(nodo==NULL){
return 0;
}
if(nodo->left==NULL&&nodo->right==NULL){
return 1;
}
return 0;
}
void espejo(Tree A) {
NodeTree*tmp;
if (A != NULL) {
if (esHoja(A)) {
return;
} else {
tmp = A->left;
A->left = A->right;
A->right = tmp;
espejo(A->right);
espejo(A->left);
}
}else{
return;
}
}

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Dado un rbol con enteros almacenados nicamente en los nodos hojas, implemente una funcin recursiva que
llene los nodos internos con valores enteros de tal manera que cada nodo almacene un entero igual a la suma de
sus hijos.
Ejemplo:
rbol antes de la llamada funcin:

rbol despus de llamar a la funcin:

Solucion:
Esta funcion debe ser recursiva. El prototipo sera como sigue: int llenarNodos(Tree arbol); mas adelante explicaremos
porque retornamos un entero.
Nuestro objetivo es ir llenando el arbol desde los nodos hijos, pasando por los nodos internos del arbol hasta llegar a
la raiz. El texto describe que un nodo padre almacenara la suma de los valores de sus nodos hijos.
La funcion implementada en la libreria int nodeTreeIsLeaf(NodeTree *p) nos retorna uno si p es un nodo hoja y cero si
no lo es.
La condicion de salida de la recursion sera cuando lleguemos a un nodo hoja, en ese momento retornamos el valor que
almacena ese nodo, por esto era necesario declarar el prototipo de la funcion como lo hicimos.
Si el nodo en analis no es hoja entonces debe tener nodos hijos. Ahora veamos la siguiente linea de codigo : int
suma=llenarNodos(nodeTreeGetLeft(arbol)) + llenarNodos(nodeTreeGetLeft(arbol));
Las funciones NodeTree*nodeTreeGetLeft(Tree A) y NodeTree*nodeTreeGetRight(Tree A) nos retornan las referencias
del subarbol izquierdo y el subarbol derecho del arbol A respectivamente.
Aqui hemos vuelto a llamar a la funcion llenarNodos pero ahora le enviamos como parametro a sus nodos hijos. En
caso de que estos sean hojas se retornara su valor almacenado,se sumaran y se guardara en la raiz. Si esto no es cierto
se seguiran haciendo llamadas a la misma funcion hasta encontrar un nodo hoja.
int llenarNodos(Tree arbol){
if(nodeTreeIsLeaf(arbol)){
return integerGet(nodeTreeGetValue(arbol));//value es un generico por eso debe extraerse el entero
que almacena
}else{
int suma=llenarNodos(nodeTreeGetLeft(arbol)) + llenarNodos(nodeTreeGetLeft(arbol));
nodeTreeSetValue (arbol , integerNew(suma));
return suma;
}
}

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Twitter mantiene por cada usuario una lista con sus mensajes ordenados en forma cronolgica, del ms reciente al
ms antiguo. Si un usuario quiere seguir a otro (ver los mensajes que publica), Twitter le da acceso a la lista de
mensajes de el usuario a seguir. Twitter funciona de tal forma que en la computadora del usuario, aparecen los 10
ltimos mensajes que fueron publicados por las personas a las que el usuario sigue. Twitter maneja los mensajes
con el siguiente TDA:
typedef struct Mensaje{
string texto;
time tiempo;
} Mensaje;
Se pide que usted escriba una funcin obtenerMensaje que reciba un arreglo de listas de mensajes de tamao N
(donde N es el nmero de usuarios a los que se se sigue en Twitter) y que retorne un heap con los 10 ltimos
mensajes. La funcin debe ser ptima en el sentido de que el recorrido de las listas debe de minimizarse.
NOTA: Asuma que el TDA Heap tiene capacidad de comparar variables de tipo time usando la funcin int
timeCmp(Generic a,Generic b);
Solucin:
Vamos a implementar la funcion: Heap*obtenerMensaje(List*Seguidos[],int n); que nos retorna un heap con los 10
ltimos mensajes que fueron publicados por las personas a la que el usuario sigue.
En este caso disponemos de un arreglo de listas, en donde dentro de estas listas se encuentran los mensajes que las
personas publican. Lo que debemos hacer es ordenar esos mensajes, de menor a mayor, y obtener los diez primeros.
Vamos a usar un heap para ordenar esos elementos.
Para construir un heap debemos conocer el numero de los k elementos que van a hacer almacenados, vamos a
estimar ese numero Como? En el arreglo de listas Seguidos, tenemos n colecciones en donde el tamao de cada
coleccin es desconocido, cada persona seguida pudo haber publicado 50,100 o 200 mensajes no lo sabemos. Lo nico
que si sabemos es que esos mensajes fueron ingresados conforme fueron publicados. Seria muy ineficiente construir
un heap con todos los mensajes de las personas seguidas, ya que mximo necesitamos conocer los diez mensajes mas
recientes de cada persona seguida. Para conocer a que valor se aproximara k haremos lo siguiente: Si una lista tiene
mas de diez mensajes, solo se tomaran en cuenta los diez primeros, si esto no es cierto iremos sumando el tamao de
esa lista al valor de k, k se ira acumulando al recorrer todas las listas del arreglo Seguidos. Cuando hayamos estimado k
ya podemos construir el heap e ir encolando los elementos correspondientes. Recuerde nuevamente se tomaran en
cuenta a lo mucho los diez primeros mensajes de cada persona seguida. Observe que k<=10xn.
Otro detalle, para construir el heap tambin debemos disponer de una funcin de comparacin entre los elementos
que sern almacenados, en este caso los mensajes sern ordenados por el tiempo, la descripcin nos dice que
disponemos de este callback as que solo haremos uso de el, no es necesario implementarlo.
Cuando hayamos construido el heap, lo ultimo que debemos hacer es desencolar diez veces, as obtendremos los diez
mensajes mas recientes, pero donde guardamos esos mensajes? En otro heap, ya que eso es lo que sugiere el
problema, este ultimo heap es el que vamos a retornar.
Cdigo:
Heap*obtenerMensaje(List*Seguidos[],int n){
List*lista;
int acumular=0,i,j;
Heap *ordenar,*mensajes;
NodeList*p;
for(i=0;i<n;i++){
lista=Seguidos[i];
if(listGetSize(lista)>10){
acumular=acumular+10;
}else{
acumular=acumular+listGetSize(lista);
}
}
ordenar=heapNew(acumular,DESC,timeCmp);
mensajes=heapNew(10,DESC,timeCmp);
Rodrigo Castro Reyes
Facultad de Ingeniera Elctrica y Computacin

for(i=0;i<n;i++){
lista=Seguidos[i];
for(p=listGetHeader(lista);p!=NULL;p=nodeListGetNext(p)){
if(j<=10){
heapEnQueue(ordenar,nodeListGetCont(p));
j++;
}else{
break;
}
}
}
for(i=0;i<10;i++){
heapEnQueue(mensajes,heapDeQueue(ordenar));
}
return mensajes;
}

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Un quad-tree es un TDA que se usa en informtica grfica para representar figuras planas en blanco y negro. Es un
rbol en cual los nodos hoja pueden representar un blanco o un negro y los nodos internos no representan ningn
color, pero siempre tienen exactamente 4 hijos. Asumiendo que la figura esta en un plano, el rbol se construye a
partir de la figura con los siguientes pasos:
1.- Dividir el plano en 4 cuadrantes.
2.- Revisar cada cuadrante en el sentido del reloj:
- Si el cuadrante esta lleno de blancos, corresponde a una hoja blanca en el rbol.
- Si el cuadrante esta lleno de negros, corresponde a una hoja negra en el rbol.
- Si el cuadrante esta parcialmente blanco y negro corresponde a un nodo interno. Aplicar el mismo algoritmo pero
para un plano que equivalga al cuadrante que se esta revisando.
El tipo de Figura puede ser una matriz de T o F de dimensiones 2 kx 2k ,donde k es la altura del quad-tree menos uno.
Ejemplo:
Figura

Quad-Tree que representa la figura

a)Definir la estructura para representar un quad-tree


b)Implemente una funcin que determine la altura del quad-tree.
c)Implemente un procedimiento que dada una figura genere el correspondiente quad-tree.
d)Implemente un procedimiento que dado un quad-tree genere la figura correspondiente.
Solucin:
a) Vamos a hacer un repaso de todas las caractersticas relevantes que describen a un Quad-tree. En este tipo de rbol
tenemos que los nodos hojas pueden tener asociados un color (Blanco o Negro) y en cambio los nodos internos no
tienen ningn color en particular. Ademas un nodo puede tener cero hijos (nodos hojas) o exactamente cuatro hijos
(nodos internos).
Vamos a definir una enumeracin Color que puede ser BLANCO,NEGRO, o NINGUNO. Un nodo posee un Color en
particular y un conjunto de hijos que a su vez son nodos tambin. Observe la definicin recursiva tpica en los arboles.
Para saber si un nodo es hoja o es interno basta con saber el tipo de color que posee. Este nodo que acabamos de
describir sera el TDA Quad-tree.
b) Ahora vamos a detallar como encontraremos la altura de este nuevo tipo de rbol. La altura de un rbol es el
numero de nodos que existe desde la raz hasta la hoja mas profunda del rbol.

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Usaremos una vez mas la recursion, dividiremos el problema en subproblemas del mismo tipo pero con menor
tamao, resolveremos estos subproblemas y combinaremos esas soluciones para encontrar la solucin final al
problema original.
Para encontrar la altura de un rbol con n hijos lo que haremos es encontrar la mxima altura entre todos los nsubarboles y sumarle el nodo raz. Para encontrar la altura de un subarbol se har exactamente lo mismo y as
sucesivamente.
Supongamos que tenemos un quad-tree que llamaremos Q de altura h. Q tiene cuatro hijos: q 1,q2,q3,q4 que son a su
vez quad-trees.
Definamos tambin la funcin maximo(h1,h2,h3,h4) que recibe cuatro enteros positivos y retorna el mayor entre ellos.
Todos estaremos de acuerdo si decimos que: h=altura(Q)= 1+ maximo(altura(q 1 ),altura(q2 )altura(q3 ),altura(q4 ))
Observe que se realizan varias llamadas recursivas, cuando estas retornen con sus respectivos resultados y la funcin
maximo haga su trabajo, obtendremos la altura de Q.
Vamos a bosquejar como se realizan estas llamadas. Primero se necesita saber el valor de altura(q 1 ). Note que q1 es
tambin un quad-tree, asumamos que es un nodo interno y que tiene como hijos a: q 11,q12,q13,q14 entonces tambin
podemos afirmar que: altura(q1) = 1+ maximo(altura(q11),altura(q12),altura(q13),altura(q14)) .
Sabemos bien que q11 es un quad-tree, ahora supongamos que es un nodo hoja, la altura de un rbol que posee un
solo nodo es uno, es aqu donde habremos definido nuestro caso base, que es necesario para el fin de la recursion.
El estado de nuestra expresin una vez que se conocio el valor de la altura de q 11 seria:
altura(q1) = 1+ maximo( 1 ,altura(q 12),altura(q13),altura(q14)) .
Ahora se necesita saber la altura de q12 y asi sucesivamente para los hijos restantes.
Luego de que se hayan calculado las respectivas alturas nuestra expresion seria:
altura(q1) = 1+ maximo( 1 ,i , j, k) , donde i,j,k representan la altura de los quad-tree hijos en cuestin, no entraremos
en detalle de como se calculan puesto que es el mismo proceso que ya hemos descrito: si son hojas su altura es uno
sino sera 1+ altura maxima entre sus quad-tree hijos.
Ahora la funcin maximo ya puede hacer su trabajo y encontrara el mayor valor entre 1,i,j,k. Luego se sumara este
resultado con uno y habremos encontrado la altura de q 1.
Luego se necesita saber el valor de altura(q 2), y como ya hemos dicho este proceso sera igual al que usamos para
encontrar la altura de q1 y asi sucesivamente para los quad-tree hijos restantes, luego de obtener esos resultados
parciales, la funcin maximo hace su tarea, se suma uno al resultado y obtenemos la altura de Q.
Es importante que usted pruebe este algoritmo con el quad-tree de prueba que nos presenta el problema, o con
cualquier otro rbol en particular, para que se pueda transparentar y entender de mejor manera como funciona la
recursion.
c) Para contestar el resto de literales vamos a presentar dos TDA's adicionales que nos sern de gran ayuda.
TDA Point: que representa un par de enteros: inicial y final.
TDA Dimension: que posee dos instancias del TDA Point: fila y columna. Este tipo de dato nos servir para almacenar la
informacin de un cuadrante, es decir los indices iniciales y finales de las filas y las columnas.
La parte clave para resolver este problema es entender como se va ir formando el quad-tree a partir de la imagen, lo
detallaremos a continuacin:

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Primero supongamos que tenemos la siguiente figura:

Es muy similar a la del ejemplo solo con la diferencia de que esta figura es una matriz de Blancos y Negros de 2 kx2k
donde k es cualquier entero positivo.
Ahora el proceso de divisin de la matriz en cuatro cuadrantes va mas o menos as:

Cuadrante uno: fila_inicial=0,fila_final=2 k-1; columna_inicial=0 columna_final= 2k-1


Cuadrante dos: fila_inicial=0,fila_final=2 k-1; columna_inicial=2k-1 +1 columna_final= 2k
Cuadrante tres: fila_inicial=2 k-1+1, fila_final=2k; columna_inicial=2k-1 +1 columna_final= 2k
Cuadrante cuatro: fila_inicial=2 k-1+1, fila_final=2k ; columna_inicial=0 columna_final= 2k-1
Cada uno de estos cuadrantes sern analizados con el siguiente criterio: si el cuadrante esta lleno de blancos se creara
una hoja dentro del quad-tree con color BLANCO, si el cuadrante esta lleno de negros se creara una hoja dentro del
quad-tree con color NEGRO, si el cuadrante tiene combinacin de blancos y negros entonces se crear un quad-tree con
color NINGUNO que tendr exactamente cuatro hijos, y es aqu en donde se vuelve a dividir la figura, en este caso el
cuadrante en anlisis es divido en cuatro planos de dimensiones de 2k-2x2k-2 cada uno, as sucesivamente. Observe que
las divisiones pararan cuando encontremos planos totalmente blancos o negros y tambin cuando tengamos planos de
20x20.
Como conclusin los problemas a resolver aqu son: conocer como ir dividiendo los cuadrantes sucesivamente y como
determinar el tipo de cuadrante que esta en anlisis.

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Hablemos mas en detalle:


Vamos a implementar el procedimiento void generarQuadTree(Color **figura, QuadTree*arbol, int filas_ini, int col_ini,
int filas_max, int col_max) que recibe una matriz que es la representacin de la figura, recibimos tambin la raz del
quad-tree y cuatro enteros que nos indica los rangos de las filas y las columnas de la matriz. En un principio las filas van
de 0 a 2k y las columnas de 0 a 2k . Donde k es un entero positivo cualquiera como ya lo hemos dicho.
Vamos a definir los cuadrantes como un conjunto de cuatro instancias del TDA Dimension, recapitulando cada
dimensin almacena cuatro elementos importantes: los indices fila inicial,fila final, columna inicial y columna final.
Antes de seguir explicando el procedimiento generarQuadTree primero explicaremos el funcionamiento de otras
funciones que usaremos para resolver el problema de forma mas sencilla.
La funcin: void asignarDimensiones(Dimension*cuadrantes[], int filas_ini, int col_ini, int filas_max, int col_max) tiene
como objetivo llenar el arreglo cuadrantes con las dimensiones correspondientes, es decir se encargara de dividir la
figura en cuatro partes segn el caso, tome mucha atencin a la implementacin que se presenta aqu.
La funcin: Color tipoCuadrante(Color **figura, Dimension *cuadrante) es la encargada de revisar la matriz figura
entre las dimensiones especificadas en la variable cuadrante. Recuerde que un cuadrante puede estar lleno de
blancos,negros o una combinacin entre esos dos colores. Observe que la variable cuadrante almacena solo los indices
que necesitamos para analizar la matriz de Blancos y Negros, es decir por ejemplo si recibimos la figura que acabamos
de mostrar y recibimos el cuadrante dos, entonces se analizara la imagen entre las filas 0 hasta 2k y entre las columnas
2k-1+1 hasta 2k.
Volvamos al procedimiento generarQuadTree: Recibimos la raz del rbol, que sera un nodo de color NINGUNO y con
cuatro nodos hijos que no sabemos de que tipo sern ya que eso depender de la figura. El conjunto de cuadrantes
sera un arreglo de dimensiones que se inicializara con la funcin asignarDimensiones que mencionamos
anteriormente.
Luego se ira iterando el conjunto de quad-tree hijos para determinar, en funcin de la imagen y el cuadrante
correspondiente, que tipo de nodo es. Vamos a determinar el tipo de cuadrante con la funcin tipoCuadrante que
describimos anteriormente.
Se empieza con el primer cuadrante y el primer hijo del quad-tree. Si la funcin tipoCuadrante retorna:
- BLANCO: el primer hijo sera de color BLANCO y se inicializa con cero hijos.
- NEGRO: el primer hijo sera de color NEGRO y se inicializa con cero hijos.
- NINGUNO: el primer hijo sera de color NINGUNO y se inicializa con cuatro hijos. Ahora se necesita dividir el primer
cuadrante y conocer el tipo de nodos correspondientes a los hijos del primer hijo. Para eso se volver a llamar a la
funcin generarQuadTree, pero en cambio la raz ahora sera el primer hijo, se enviara la misma figura, pero las
dimensiones de anlisis cambiaran, estos datos los almacena el primer cuadrante. Observe que este tambin es un
proceso recursivo. Cuando se haya completado de construir este sub-quad-tree se podr seguir iterando con el
segundo hijo y el segundo cuadrante, luego el tercer hijo y el tercer cuadrante, despus el cuarto hijo y cuarto
cuadrante, con esto terminamos de construir el rbol original.
Nuevamente, se anima a que se realice una prueba de escritorio con el algoritmo que hemos descrito para que se
pueda entender en su totalidad.
El ultimo procedimiento que nos piden implementar es void generarFigura(Color**figura, QuadTree*arbol, int
filas_ini,int filas_max, int col_ini,int col_max) que recibe una matriz vaca, las dimensiones de la matriz y la raz de un
quad-tree que representa a una figura.
Haremos un proceso muy similar al de la funcin anterior. Tendremos un conjunto de cuadrantes que se formaran de
las misma forma que ya se explico. Vamos a iterar los hijos del nodo raz que recibimos por parmetro y el conjunto de
cuadrantes.
Se empieza con el primer hijo y con el primer cuadrante. Si el primer hijo es de color:
-BLANCO: el primer hijo representa un cuadrante lleno de blancos Que cuadrante? En este caso el primero.
Luego, llenamos la figura con el color BLANCO entre las dimensiones definidas en el cuadrante.
-NEGRO: el primer hijo representa un cuadrante lleno de negros Que cuadrante? En este caso el primero.
Luego, llenamos la figura con el color NEGRO entre las dimensiones definidas en el cuadrante.
-NINGUNO: significa que el primer hijo representa un cuadrante lleno de blancos y negros. Esto quiere decir que se
Rodrigo Castro Reyes
Facultad de Ingeniera Elctrica y Computacin

necesita analizar este cuadrante y los hijos del primer hijo. Lo que haremos es volver a llamar a la funcin
generarFigura, envindole las nuevas dimensiones de anlisis (las del primer cuadrante). Luego de resolver este
subproblema seguimos analizando el segundo hijo y el segundo cuadrante, despus el tercer hijo y el tercer cuadrante,
y por ultimo el cuarto hijo y el cuarto cuadrante. Observe que en cada anlisis se pueden realizar varias llamadas
recursivas. Nuevamente se aconseja que realice una prueba siguiendo cada paso de la solucin, es la nica forma de
terminar de entender por completo como funciona la recursion.
Presentamos un pequeo programa para probar los procedimientos que hemos diseado. Primero se genera la figura
del ejemplo que nos muestra la descripcin, en base a ella construimos un quad-tree. Tambin se calcula la altura del
quad-tree y se muestra por pantalla. Luego se declara una matriz de colores de 2 kx2k donde k es el nivel del quadtree
que es calculado restando la altura del rbol con uno. Se inicializa la matriz con el color NINGUNO. Esta figura sera
llenada en funcin del rbol que generamos anteriormente.
Cdigo:
typedef enum Color {
NEGRO, BLANCO, NINGUNO
} Color;
typedef struct QuadTree {
Color color;
struct QuadTree **hijos;
} QuadTree;
typedef struct {
int inicial, final;
} Point;
typedef struct {
Point *fila, *columna;
} Dimension;
QuadTree*quadTreeNew(Color color) {
QuadTree *arbol = malloc(sizeof (QuadTree));
arbol->color = color;
if (color == NINGUNO) {
arbol->hijos = malloc(sizeof (QuadTree*)*4);
} else {
arbol->hijos = NULL;
}
return arbol;
}
Dimension*dimensionNew(Point*fila, Point*columna) {
Dimension*dimension = malloc(sizeof (Dimension));
dimension->fila = fila;
dimension->columna = columna;
return dimension;
}

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

Point *pointNew(int inicial, int final) {


Point*p = malloc(sizeof (Point));
p->inicial = inicial;
p->final = final;
return p;
}
Color**figuraNew(int dimension, Color color) {//genera una matriz de colores de dimensionxdimension
int i, j;
Color**figura;
figura = malloc(sizeof (Color*) * dimension);
for (i = 0; i < dimension; i++) {
figura[i] = malloc(sizeof (Color) * dimension);
}
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
figura[i][j] = color;
}
}
return figura;
}
int alturaQuadTree(QuadTree *arbol) {
if (arbol->color == BLANCO || arbol->color == NEGRO) {
return 1;
} else {
return 1 + maximo(alturaQuadTree(arbol->hijos[0]), alturaQuadTree(arbol->hijos[1]),
alturaQuadTree(arbol->hijos[2]), alturaQuadTree(arbol->hijos[3]));
}
}
int maximo(int w, int x, int y, int z) {
int max, i, array[4];
array[0] = w;
array[1] = x;
array[2] = y;
array[3] = z;
max = array[0];
for (i = 1; i < 4; i++) {
if (max < array[i]) {
max = array[i];
}
}
return max;
}

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

void asignarDimensiones(Dimension*cuadrantes[], int filas_ini, int col_ini, int filas_max, int col_max) {
cuadrantes[0] = dimensionNew(pointNew(filas_ini, filas_ini + (filas_max - filas_ini) / 2),
pointNew(col_ini, col_ini + (col_max - col_ini) / 2));
cuadrantes[1] = dimensionNew(pointNew(filas_ini, filas_ini + (filas_max - filas_ini) / 2),
pointNew(col_ini + (col_max - col_ini) / 2 + 1, col_max));
cuadrantes[2] = dimensionNew(pointNew(filas_ini + (filas_max - filas_ini) / 2 + 1, filas_max),
pointNew(col_ini + (col_max - col_ini) / 2 + 1, col_max));
cuadrantes[3] = dimensionNew(pointNew(filas_ini + (filas_max - filas_ini) / 2 + 1, filas_max),
pointNew(col_ini, col_ini + (col_max - col_ini) / 2));
}
Color tipoCuadrante(Color **imagen, Dimension *dimension) {
Point*fila, *columna;
fila = dimension->fila;
columna = dimension->columna;
int i, j;
Color color;
int flag;
for (i = fila->inicial; i <= fila->final; i++) {
for (j = columna->inicial; j <= columna->final; j++) {
color = imagen[i - 1][j - 1];
switch (color) {
case BLANCO:
if (flag == 1) {
return NINGUNO;
}
flag = 0;
break;
case NEGRO:
if (flag == 0) {
return NINGUNO;
}
flag = 1;
break;
}
}
}
if (flag) {
return NEGRO;
} else {
return BLANCO;
}
}

Rodrigo Castro Reyes


Facultad de Ingeniera Elctrica y Computacin

void generarQuadTree(Color **figura, QuadTree*arbol, int filas_ini, int col_ini, int filas_max, int col_max) {
int i;
Dimension * cuadrantes[4];
asignarDimensiones(cuadrantes, filas_ini, col_ini, filas_max, col_max);
for (i = 0; i < 4; i++) {
switch (tipoCuadrante(figura, cuadrantes[i])) {
case BLANCO:
arbol->hijos[i] = quadTreeNew(BLANCO);
break;
case NEGRO:
arbol->hijos[i] = quadTreeNew(NEGRO);
break;
case NINGUNO:
arbol->hijos[i] = quadTreeNew(NINGUNO);
generarQuadTree(figura, arbol->hijos[i], cuadrantes[i]->fila->inicial, cuadrantes[i]->columna->inicial,
cuadrantes[i]->fila->final, cuadrantes[i]->columna->final);
break;
}
}
}
void generarFigura(Color**figura, QuadTree*arbol, int filas_ini, int filas_max, int col_ini, int col_max) {
int i, j, k;
QuadTree *hijo;
Dimension*dim;
Point*fila, *columna;
Dimension * cuadrantes[4];
asignarDimensiones(cuadrantes, filas_ini, filas_max, col_ini, col_max);
for (i = 0; i < 4; i++) {
hijo = arbol->hijos[i];
dim = cuadrantes[i];
fila = dim->fila;
columna = dim->columna;
if (hijo->color != NINGUNO) {
for (j = fila->inicial; j <= fila->final; j++) {
for (k = columna->inicial; k <= columna->final; k++) {
figura[j-1][k-1] = hijo->color;
}
}
} else {
generarFigura(figura, hijo, fila->inicial, columna->inicial, fila->final, columna->final);
}
}
}
Rodrigo Castro Reyes
Facultad de Ingeniera Elctrica y Computacin

Das könnte Ihnen auch gefallen