Beruflich Dokumente
Kultur Dokumente
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
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.
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:
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:
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.
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.
El rbol resultante es el que se muestra a continuacin, observe que se cumplen estrictamente las indicaciones del
texto.
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.
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.
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.
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.
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.
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
12
15
25
12
30
18
Seguimos el mismo procedimiento que ya conocemos para formar un arbol de Huffman obteniendo lo siguiente:
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;
}
}
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;
}
}
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:
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;
}
}
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;
}
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
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:
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:
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;
}
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;
}
}
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