You are on page 1of 20

APLICACIONES DE RBOLES A LA TEORA DE LENGUAJE TEORA DE LENGUAJE

Introduccin El ordenador solo entiende el llamado cdigo mquina (1 y 0, hay o no hay corriente). Los lenguajes de programacin de alto nivel permiten dar rdenes al ordenador con un lenguaje parecido al nuestro (Visual Basic, Pascal, GML, LOGO, C++, etc). El problema de los lenguajes de alto nivel es que necesitan un compilador o interprete para traducirlo al cdigo mquina. Hay otros programas como el GML o el Java que son programas interpretados, es decir, se analizan y ejecutan las instrucciones por el propio programa. Los lenguajes ms cercanos al idioma del ordenador, llamados de bajo nivel, son muy complicados (casi como el cdigo mquina) y poco usados. Los lenguajes, como todo, hay que aprendrselos, pero tienen una ventaja, y es que hay varios puntos en comn. Comentarios Poner comentarios de lo que vamos haciendo es muy til, sobre todo cuando llega la hora de revisar el programa, si no, ms de una vez nos encontraremos diciendo qu haca esto aqu? No cuesta nada documentar el programa y nos ahorrar dolores de cabeza. La norma que seguiremos ser poner // delante de los comentarios, para identificarlos: // Esto ser un comentario y no har nada en el programa LAS VARIABLES Una variable es como una caja donde metemos cosas (datos). Estos datos los podemos ir cambiando, ahora meto un 3 ahora lo quito y meto un 5. Una variable tiene un nombre, que puede ser una letra, una palabra, varias palabras unidas por el guin bajo o varias palabras sin separar pero la primera letra de cada palabra en maysculas ejem.: VidasPerdidas. Las variables tambin tienen un valor que sera lo que habra dentro de ella (en la caja) en ese momento y que puede ir variando segn se vaya desarrollando el programa, por eso se llama variable.
ESTRUCTURAS DISCRETAS Pgina 1

Una variable dependiendo de su valor puede ser numrica, si solo puede tener un valor numrico, de texto, si solo puede contener texto (letra, palabra o frase (string)). En las variables de texto, su valor (el texto), debe ir entre comillas, para diferenciar que el texto es texto y no es el nombre de otra variable. Hay otras variables que se llaman booleanas que solo pueden tener dos valores true o false (algunas veces true se puede sustituir por el 1 y false por el 0). Ejemplos: Edad=3 //variable numrica

variableDeTexto= Edad variableNumerica=Edad+2 //su valor es el valor de la variable Edad (numrica) +2; en este caso sera=5 variableBooleana=true; podra ser 1 Lo normal es declarar las variables al principio de un programa. Declarar no es ms que decir "mira, yo quiero tres variables, y quiero que una se llame Nombre, otra Edad y otra Apellido". A partir de este momento, podrs meter, por ejemplo, Juan en Nombre, un 5 en Edad y Rodrguez en Apellido. Ojo no es la misma variable Nombre que nombre. Las variables se suelen declarar al principio del programa. NUMRICA: Pepe //declaramos la variable Pepe. En GML no hace falta.

Pepe = 14 //Damos un valor a la variable ya declarada Pepe; Pepe = 42 // Cambiamos el valor d la variable a 42; Fijate que ponemos ; antes de pasar a la siguiente instruccin. Esto siempre se debe hacer as. Podemos sumar, restar, multiplicar y dividir variables. NUMRICA: Pepe, Mari ,Juan //Declaramos las variables que usaremos;
ESTRUCTURAS DISCRETAS Pgina 2

Pepe=2; Mari=3; Juan =Pepe+Mari; // Juan tiene el valor numrico de 5 Hay variables ya definidas por el propio lenguaje de programacin que usemos, y cuyo nombre no se lo podremos dar a ninguna de las que nosotros definamos. Las podemos usar pero tal y como el lenguaje las defini. Por ejemplo en GML mouse_x es la variable que tiene el valor de la posicin x del ratn en cada momento, hspeed es la velocidad horizontal, etc. Si queremos que la variable se use en todo el programa deberemos nombrarla como una variable global, en caso contrario variable local, la variable al salir del lugar donde le hemos asignado un valor, perder ese valor y ya no existir (al salir de un algoritmo, trozo de programa, del objeto, de una estructura IF, etc). En GML se pone la palabra global. Y detrs el nombre de la variable, de esta forma servir para el programa entero. Ejemplo global.pepe, que ser distinta de la variable pepe.

PROGRAMAS Y ALGORITMOS
Los lenguajes de programacin, cuentan todos en su haber con un juego de "instrucciones". Una instruccin no es ms que una orden que nosotros le damos a la mquina. Y es que, al fin y al cabo, un PROGRAMA no es ms que una secuencia de instrucciones (escritas en algn lenguaje de programacin) pensado para RESOLVER algn tipo de PROBLEMA. Si no sabemos resolver este problema, no podremos escribir el programa. A ti se te puede ocurrir una manera de resolverlo, a tu compaero, otra. Este METODO con el que resolvis el problema, es lo que se llama ALGORITMO, y es lo que vamos a ver a continuacin. Un algoritmo es una secuencia de PASOS a seguir para resolver un problema.
ESTRUCTURAS DISCRETAS Pgina 3

Por ejemplo, cuando quiero ver una pelcula de vdeo, podra hacer: Elijo una pelcula de las de mi coleccin. Compruebo SI TV y vdeo estn conectados a la red (y procedo). SI la TV est apagada, la enciendo, SI NO, pues no. Y lo mismo con el vdeo. Introduzco la pelcula en el vdeo. Dejo el estuche sobre el vdeo. SI la TV no est en el canal adecuado, la cambio, SI NO, pues no. Cojo los mandos a distancia (el del TV y el del vdeo). Me pongo cmodo. Pulso PLAY en el mando del vdeo. Fijaos bien en unos detalles que son fundamentales y que aparecen en este algoritmo: - La descripcin de cada paso no me lleva a ambigedades: los pasos son absolutamente explcitos y no inducen a error. - El nmero de pasos es finito. Tienen un principio y un fin. Segn lo visto una mejor definicin de algoritmo sera: Un algoritmo es una sucesin finita de pasos (no instrucciones como en los programas) no ambiguos que se pueden llevar a cabo en un tiempo finito. Hay distintas formas de escribir un algoritmo, bien usando un lenguaje especfico de descripcin de algoritmos, bien mediante representaciones grficas: diagramas de flujo. Nosotros vamos a usar un lenguaje llamado pseudocdigo, y a la vez pondremos tambin las instrucciones que se deberan poner en el lenguaje de programacin GML. Segn avancemos haremos solo programas en GML (que es lo que finalmente nos interesa).
ESTRUCTURAS DISCRETAS Pgina 4

Independiente del lenguaje de programacin que vaya a usarse; un algoritmo que est escrito en pseudocdigo o con un diagrama de flujo es fcilmente traducible a muchos lenguajes de programacin.

ESTRUCTURAS DE CONTROL
Las estructuras de control tienen una finalidad bastante definida: su objetivo es ir sealando el orden en que tienen que sucederse los pasos de un algoritmo o de un programa. Las estructuras de control son de tres tipos:

Secuenciales Selectivas Repetitivas

ESTRUCTURAS DISCRETAS

Pgina 5

La teora de lenguajes de programacin es una rama de la informtica que se encarga del diseo, implementacin, anlisis, caracterizacin y clasificacin de lenguajes de programacin y sus caractersticas. Es un campo multidisciplinar, dependiendo tanto de (y en algunos casos afectando) matemticas, ingeniera del software, lingstica, e incluso ciencias cognitivas. Su estudio est orientado a: El programador profesional, que necesita saber las diferencias entre los LP para poder elegir el ms adecuado para el proyecto que quiera realizar o el problema a resolver o, si ya ha tomado esta decisin y trabaja con uno concreto, para mejorarlo con tcnicas disponibles en otros LP. El diseador de un nuevo LP que necesita saber tanto los fundamentos de los diferentes paradigmas de los LP como el panorama completo de los existentes El implementador de un LP que desarrolla su compilador o intrprete sobre una mquina particular o un tipo de mquina y pueda aprovechar lo que ha aprendido en este mismo proceso para futuros LP.

En general el programador, el diseador y el implementador de un LP deben conocer el rea de los LP, su evolucin histrica, sus fundamentos tericos, los distintos usos, etc. para poder apreciar sus caractersticas diferentes, entender la influencia que ejercen las arquitecturas y aplicaciones de los ordenadores sobre el diseo de los LP y evitar futuros defectos de diseo de programas aprendiendo las lecciones del pasado.

APLICACIONES DE ARBOLES
Un rbol es una estructura que implica una jerarqua, en la que cada elemento est unido a otros bajo l. Cada dato en un rbol es un nodo de dicho rbol. El nodo ms alto se denomina raz. Un nodo es la unidad sobre la que se construye el rbol y puede tener cero o ms nodos hijos conectados a l. Se dice que un nodo es padre de un nodo si existe un enlace desde hasta (en ese caso, tambin decimos que es hijo de).
ESTRUCTURAS DISCRETAS Pgina 6

Slo puede haber un nico nodo sin padres, que llamaremos raz. Un nodo que no tiene hijos se conoce como hoja. Los dems nodos (tienen padre y uno o varios hijos) se les conoce como rama.

Formalmente, podemos definir un rbol de la siguiente forma: Caso base: un rbol con slo un nodo (es a la vez raz del rbol y hoja). Un nuevo rbol a partir de un nodo una de las races de los nodo, los nodos y rboles de races con y cada nodos tiene como raz l y el conjunto de nodos hoja est formado por la unin elementos cada uno, puede construirse estableciendo una relacin padre-hijo entre rboles. El rbol resultante de son los hijos de los conjuntos hojas iniciales. A cada uno de los rboles se les denota ahora subrboles de la raz. Una sucesin de nodos del rbol, de forma que entre cada dos nodos consecutivos de la sucesin haya una relacin de parentesco, decimos que es un recorrido rbol. Una de las estructuras de datos ms importantes en programacin es el rbol. Pueden usarse los rboles para representar la informacin en una estructura jerrquica. Los rboles pueden procesarse en forma recursiva y son muy adaptables a pruebas matemticas. El estudio de rboles ilustra las conexiones entre varios temas de la matemtica discreta y ofrece oportunidades para aprovechar la matemtica formal en la programacin prctica. La idea de estructura jerrquica es muy usada en la prctica. Por ejemplo, los libros son a menudo organizados como una sucesin de captulos cada uno de los cuales son una sucesin de secciones que puede tener subdivisiones, y as sucesivamente. Una empresa puede organizarse como las colecciones de unidades comerciales cada uno de las cuales pueden tener varias secciones. Las secciones, a su vez, pueden tener secciones mltiples, y as sucesivamente. El software es organizado como una coleccin de mdulos cualquiera que pueden constituirse de varios sus mdulos, con el nivel de refinamiento que los diseadores encuentren apropiado.
ESTRUCTURAS DISCRETAS Pgina 7

En cierto nivel, los mdulos se expresan en unidades bsicas como los objetos, los mtodos, o procedimientos. En otros trminos, las estructuras jerarquas proporcionan una eficaz la manera de organizar la informacin. Los rboles proporcionan una capacidad enorme para expresar la idea de jerarqua. Ellos son objetos formales, matemticos. Son muy utilizados en informtica. Las partes de muchos programas se enlazan como si se tratara de rboles. Los rboles se utilizan para representar operaciones aritmticas, y en bsquedas y ordenaciones. La forma usual de representar los rboles supone el uso de punteros. En un rbol binario cada nodo est constituido por una parte de datos y dos punteros. Uno, o ambos punteros, pueden tener un valor nulo si del nodo no cuelgan subrboles.

EL RBOL DE NODOS
Antes de implementar la clase "Tree" es necesario definir qu es un rbol. Los rboles son grafos, pues estn compuestos de nodos y aristas que los unen. Para definir matemticamente un rbol es necesario definir primero el concepto de Camino, que es una secuencia de aristas que conectan nodos, en que la arista siguiente en el camino comienza en el nodo en que termina la arista anterior. UnCircuito es un camino en el que el primer y ltimo nodo son el mismo, y un Circuito simple es un circuito en que cada nodo aparece slo una vez. Se dice que el grafo es Conectado si siempre existe un camino entre cualesquiera 2 nodos del grafo. Con base a estos conceptos son equivalente las siguientes definiciones matemticas del rbol "T" [Even-79]: 1. "T" es un grafo conectado que no tiene circuitos simples.

ESTRUCTURAS DISCRETAS

Pgina 8

2. "T" no tiene circuitos simples, pero si a "T" se le agrega cualquier arista se forman un circuito. 3. "T" es un grafo cuyos nodos no estn conectados consigo mismos en el que siempre existe un nico camino entre cualesquiera 2 nodos. 4. "T" es un grafo conectado, pero si una arista de "T" es removida el resultado es que "T" queda desconectado. 5. "T" tiene "n" nodos y no tiene circuitos, y tambin tiene exactamente "n1" aristas. 6. "T" es un grafo conectado de "n" nodos que tiene exactamente "n-1" aristas. Todas estas definiciones son escuetas, correctas y completas pero, paradjicamente, no hablan de las propiedades principales de los rboles, por lo menos desde el punto de vista del programador, pues no mencionan que un rbol en una jerarqua encabezada por su raz. De hecho, en estos rboles matemticos cualquier nodo podra fungir como nodo raz. Estos hechos son muestra de que el concepto de rbol no es fcil de definir, pues tiene muchos posibles significados (qu es un rbol binario?). Una forma de definir qu es un rbol es mostrar cmo est hecho. En los libros de texto lo usual es definir un rbol como un conjunto finito de elementos o nodos organizados de acuerdo a las siguientes propiedades: 1. T es un conjunto finito, o vaco, de elementos almacenados en "nodos" [T.Empty()]. 2. Los nodos del rbol estn conectados unos a otros por medio de aristas o enlaces. 3. Un rbol no vaco siempre tiene un nico nodo llamado la "raz" del rbol [T.Root()] del que todos los dems nodos son descendientes [T.Child(i)]. 4. Cada nodo en el rbol, excepto el nodo raz, tiene un nico nodo del que desciende directamente. Ese nodo es el nodo padre [T.Father()].
ESTRUCTURAS DISCRETAS Pgina 9

5. Dos nodos que tienen el mismo padre se llaman hermanos [T.Sibling(i)]. 6. Los nodos que no tienen descendientes se llaman nodos hoja [Is_Leaf(T) ]. 7. La longitud del camino que separa a un nodo de la raz se conoce como su "profundidad" [Depth(T) ]. 8. La longitud del camino ms largo desde un nodo a alguno de sus descendiente es la altura del nodo [Height(T) ]. 9. La altura del rbol es la altura de su raz. 10. Entre cualesquiera dos nodos del rbol siempre existe un nico camino que los une. 11. Los descendientes de un nodo siempre estn ordenados de izquierda a derecha [T.Child(i)]. 12. Cada nodo puede tener un hijo nmero "n" aunque no tenga hijos anteriores o posteriores. Las ltimas 2 condiciones son necesarias para que la definicin de lo que es un rbol sea completa, pues al eliminarlas ocurre que los dos rboles binarios que tengan uno un hijo izquierdo y otro el mismo hijo, pero a la derecha, seran iguales.

El rbol hecho con base en la lista

ESTRUCTURAS DISCRETAS

Pgina 10

T=A /|\ BCD /\ L M /\ \ /

L D \ M

Figura 1 Un truco bien conocido es el de usar un rbol binario para representar los valores de un rbol "n"-ario, como se muestra en la Figura 1. La forma de hacerlo es bastante simple, pues ambos rboles tienen la misma raz. En el rbol binario, el hijo izquierdo siempre es el primer hijo del rbol "n"-ario, mientras que los hijos derechos del rbol binario son los hermanos del hijo izquierdo. Como sobra un puntero a la derecha en el nodo del ltimo hijo (en los nodos "D" y "M"), queda muy conveniente poner ah un puntero al padre, Lo que se ha enfatizado en la figura al usar doble lnea. Todos los punteros en el rbol se usan, y nicamente el nodo raz tiene su puntero derecho nulo, pues en un rbol slo la raz no tiene nodo padre. Esta estructura de datos es muy compacta y eficiente [HS-92]. El inconveniente de estos rboles llamados "Hijo-izquierdo Hermano Derecho" es que para llegar al hijo nmero "n" hay que visitar antes a todos los hijos anteriores, mientras que en el rbol implementado con un vector de punteros a
ESTRUCTURAS DISCRETAS Pgina 11

los hijos esta operacin es inmediata, pues en un vector la cantidad de tiempo para llegar a cualquiera de sus elementos siempre es la misma. La ventaja de los rboles hijo+hermano es que no desperdician espacio en punteros nulos, y adems sirven para representar de manera natural cualquier rbol "n"-ario, pues no tienen la limitacin de un mximo de hijos por nodo (siempre y cuando haya memoria dinmica suficiente). Por eso, en muchas ocasiones es preferible usar rboles hijo+hermano, pues no requieren del programador cliente grandes cuidados para evitar sobrepasar el lmite de nmero de hijos. Al implementar los rboles hijo+hermano surgen algunas dificultades que hay que mencionar. Lo primero es que se hace necesario incluir en el nodo algn marcador que permita diferenciar si un puntero derecho apunta a otro hermano, o si ms bien ah est el puntero al nodo padre que tiene el ltimo hermano. Existen varios trucos de programacin para lograr esta diferenciacin entre los que se pueden destacar dos. El primero, y tal vez el menos complicado, es esconder en el puntero final un "bit que indique si ese puntero es o no un puntero al padre, usando un truco de programacin similar al expuesto. La razn por la que aqu no se usa el truco del "bit escondido" es que es difcil de explicar a estudiantes novatos, y adems se puede lograr el mismo efecto con la otra alternativa descrita ms adelante.

// (m_n_child < 0) ==> Es el puntero al padre

class Tree_Node { private: value_type m_data; unsigned int m_refCount;

m_n_child; // incrementado en int(1)

Tree_Node * m_left_child;

ESTRUCTURAS DISCRETAS

Pgina 12

Tree_Node * m_right_brother; }; // Tree_Node

Figura 2 Es necesario incluir en el nodo el campo "m_n_child" para registrar cul es el nmero de hijo entre todos los hijos de un mismo padre, que se obtiene con el mtodo "Child_Number ()"; ah se puede tambin indicar si un nodo es el ltimo en la lista de hijos de su padre, almacenando un valor negativo en el campo "m_n_child". El campo "m_refCount" sirve para mantener un contador de referencias, lo que facilita mucho el trabajo con rboles y sus sub-rboles. Como en C++ todos los ndices comienzan en cero "0" (no como en Pascal o Fortran, en donde comienzan en uno "1") en muchos casos existir el hijo nmero cero (de hecho, el hijo izquierdo en un rbol binario es precisamente "Child (0)"). Sin embargo, el cero tiene la particularidad de que es el nico nmero que es igual a su negativo "0 == -0", por lo que el campo "m_n_child" no podra contener un nmero negativo para el nico hijo nmero cero. Por eso, en la implementacin se almacena el valor "-n-1" o el valor "+n+1" en el campo "m_n_child" dependiendo de si el nodo es o no el ltimo en la lista de hijos del nodo padre. En la discusin que sigue su usa la implementacin de listas de la clase rbol, llamada "TL::Tree"; tambin se realiz la implementacin "TV::Tree" usando un vector de punteros, que es funcionalmente equivalente a "TL::Tree", pero cuyas cualidades de rendimiento no son discutidas ac por razones de espacio.

Funcionalidad del rbol En las secciones anteriores la mayor parte de la discusin se hizo desde la ptica de la implementacin, por lo que fue necesario usar la palabra "Nodo" muchas veces. Como ocurre con las listas de Lisp, es posible especificar el rbol sin usar el concepto de "Nodo", usando ms bien sub-rboles, as como la listas Lisp estn definidas en trmino de sus sub-listas. Por analoga con Lisp, un sub-rbol es una parte de un rbol.

ESTRUCTURAS DISCRETAS

Pgina 13

Lo ms simple muchas veces es suficiente; afortunadamente, basta definir un sub-rbol como un objeto que contiene una referencia hacia el valor almacenado en la jerarqua que representa la raz del sub-rbol. La diferencia principal entre rboles y sub-rboles es que los primeros nunca tendrn en su raz una indicacin de quien es su padre, pues por definicin la raz un rbol no tiene padre alguno, mientras que s puede ocurrir que un sub-rbol descienda de algn nodo por lo que en ese caso su raz tendra un padre no vaco. Una vez que se usa el concepto de "sub-rbol" en lugar del de "nodo" se puede prescindir completamente de los nodos, porque en lugar de manipular los nodos se puede manipular sub-rboles cuya raz es el "nodo" (que ya no hace falta mencionar). Por eso, la especificacin de la operacin "Child(n)" dice que retorna el "n"-simo sub-rbol hijo, no que retorna un nodo. Desafortunadamente, al definir los rboles como referencias surge un problema adicional, pues hay que mantener un control de cuntas referencias existen para cada nodo del rbol. Habr ms de una referencia al mismo sub-rbol si, por ejemplo, para el mismo rbol se invoca ms de una vez la operacin "Child(n)". Los rboles son tiles porque, adems de almacenar valores, lo hacen imponiendo una estructura que permite luego lograr eficiencia en muchos algoritmos. Por eso, es importante definir cules mecanismos existen para pasar de un valor almacenado en el rbol a otro, y cmo se usan esos mecanismos. Los iteradores lineales de la biblioteca STL estndar de C++ son bien conocidos, pero a fin de cuentas no reflejan la estructura no lineal de los rboles. Por eso, el mecanismo principal para recorrer un rboles es visitar al padre y a sus hijos mediante la invocacin de los mtodos "Father ()" y "Child(n)". Los rboles son contenedores, por lo que deben incluir operaciones que permitan almacenar valores en el rbol. Para sto hay que contar por lo menos con 2 mecanismos: uno para cambiar un valor individual y el otro para injertar sub-rboles completos. Para agregar o cambiar un valor en la raz se usa "Change_Root (d)", y para hacer lo mismo en el "n"-simo hijo se usa "Change_Child(n, d)". El mtodo "Graft(n, Ti)" sirve para agregar el sub-rbol "Ti" completo, como "n"-simo hijo de "T". Los mtodos "Erase ()" junto con "Erase_Son(n)" tiene el efecto inverso, pues eliminan el sub-rbol completo. Como ocurre con cualquier objeto, tambin para los rboles tiene sentido definir sus operaciones elementales de copia, impresin, etc. Al copiar un rbol, que es una referencia, lo que se copia es una referencia, y el resultado es una copia superficial de valores. Por eso la operacin "Copy ()" es una copia
ESTRUCTURAS DISCRETAS Pgina 14

superficial, y si se necesita una copia profunda del rbol, hay que usar "Copy_Deep ()". Como se usa semntica de referencia para implementar rboles, las operaciones para recorrer los valores almacenados en el rbol retornan un nuevo objeto sub-rbol cuando, como lo hace por ejemplo "Child(n)". Esas referencias no son los valores almacenados del rbol y en consecuencia al intercambiarlas, mediante el mtodo "Swap ()" o al copiarlas, mediante el mtodo "Copy ()", no se modifica los valores almacenados en el rbol. Para modificar los valores almacenados es necesario usar los mtodos que realizan esa funcin, como lo son "Change_Root (d)", "Change_Child(n,d)" o "Graft(n,Ti)". Por eso, si se usa "Swap ()" para intercambiar 2 rboles obtenidos mediante invocaciones a "Child(n)" no se lograr cambiar los valores de los rboles originales.

/** Convierte a "T" en su sub-rbol espejo, en el que recursivamente los hijos quedan en orden inverso del orden en el que aparecan originalmente en "T"

a /|\ //\\ b cd e /|\ /|\ /|\

a /|\ //\\ e dc b /|\

fgh ijk /\ lm

kji hgf /\ ml

ESTRUCTURAS DISCRETAS

Pgina 15

/\ no */

/\ on

void Mirror( Tree& T ) { if ( T.Empty() ) { return; // se sale si el rbol est vaco }

Tree Child = T.Leftmost(); while ( ! Child.Empty() ) { // recursin para cambiar a todos los hijos Mirror( Child ); Child = Child.Right_Sibling(); }

unsigned N = T.Rightmost_N(); Tree Ti, Tn_i; // [0] [1] [2] [3] [4] N == 4

unsigned i, Mid = (N+1) / 2; // i i < 2 == Mid ==> 2 == 4/2 == 5/2

ESTRUCTURAS DISCRETAS

Pgina 16

for (i=0; i<Mid; ++i) { // Intercambia los hijos i <==> N - i Ti = T.Child( i ); Tn_i = T.Child( N - i ); T.Graft( i, Tn_i ); assert(( Ti.Empty() ? true : Ti.Father().Empty() ));

T.Graft( N - i, Ti ); } }

// [0] [1] [2] [3] [4]

N == 4

unsigned i, Mid = (N+1) / 2; // i i < 2 == Mid ==> 2 == 4/2 == 5/2 for (i=0; i<Mid; ++i) { // Intercambia los hijos i <==> N - i T.Child(i) . Swap ( T.Child( N - i ); } // \====/

Figura 3 En la parte de arriba de la Figura 3 est la implementacin de la funcin "Mirror (T)" que funciona porque recursivamente vuelve al revs a "T" y a todos sus sub-rboles. La Figura 3 es muestra de que es posible implementar algoritmos recursivos de manera natural cuando se usa el concepto de "Sub-rbol" en lugar del de "Nodo". En esto tambin ayudan las cualidades sintcticas del lenguaje C++,

ESTRUCTURAS DISCRETAS

Pgina 17

cuyos mecanismos de herencia y sobrecarga de nombres permiten escribir con naturalidad los algoritmos, sin sacrificar el ocultamiento de datos. El algoritmo "Mirror(T)" implementado en la Figura 3 tambin sirve para ver que es muy cmodo usar sub-rboles pues, para simplificar la implementacin, dentro del ciclo "for" se usan los 2 sub-rboles temporales "Ti" y "Tn_i". Al principio del ciclo "for" el resultado de la asignacin "Ti = T.Child (i)" es hacer que el valor de "Ti" sea un sub-rbol cuyos valores estn almacenados como sub-rbol de "T", con lo que efectivamente "T" y "Ti" comparten sus valores almacenados (esto quiere decir que si se ejecutara la operacin "Ti.Change_Root (d)" cambiara tanto el valor de "Ti" como el de "T"). Despus de la ejecucin de la operacin "T.Graft (i,Tn_i)" ya no hay valores comunes entre "T" y "Ti", pero s ocurre que "Ti" mantiene los valores que fueron parte de "T". Por eso, pese a que la operacin "T.Graft(i,Tn_i)" elimina "Ti" como subrbol de "T", en "Ti" quedan los valores que luego son instaladas como el hijo nmero "N-i" gracias la ltima operacin del ciclo, operacin "T.Graft(N-i,Ti)" Para intercambiar los sub-rboles de la posicin "i" a "N-i" en "Mirror (T)" es necesario usar "Graft(n, Ti)" pues si se usara un simple "Swap ()", como est en la parte de abajo de la Figura 3, el resultado sera intercambiar las nuevas referencias a los hijos de "T" que "Child(n)" retorna, pero eso no cambia los valores almacenados en "T". En otras palabras, el efecto de esa invocacin a "Swap ()" sera dejar el rbol "T" con su valor original, e intercambiar las referencias que contienen los sub-rboles temporales que las 2 invocaciones a "Child ()" produciran, lo que no tiene efecto en el valor de "T". Despus de que un estudiante logra comprender por qu es necesario usar "Graft(n, Ti)" en lugar del simple "Swap ()", ya no tendr dificultad en saber cmo funcionan los lenguajes que usan la semntica de referencia como mecanismo fundamental para manipulacin de datos, como ocurre en los lenguajes Java y C#. Despus de analizar la implementacin del algoritmo "Mirror (T)" en la Figura 3 es natural deducir la especificacin de cada una de las operaciones de la clase "Tree". La clase "TL: Tree" facilita la escritura de algoritmos recursivos que manipulan la estructura del rbol, sin importar cul es su contenido, porque el acoplamiento entre los valores almacenados y el contenedor es muy bajo.

ESTRUCTURAS DISCRETAS

Pgina 18

class Bin_Tree { Node * m_root; public: struct Node { Node *m_left, *m_right; value_type m_data; }; friend void Print0( Node * ); void Print() { Print0(m_root); } };

// Print0() trabaja con nodos // - No trabaja con el rbol void Print0( Bin_Tree::Node *p) { if (p != 0) { Print0( p->m_left ); cout << p->m_data << ' '; Print0( p->m_right ); } }

Figura 4 Tradicionalmente, los algoritmos recursivos que trabajan con rboles tienen que ser implementados en 2 partes, en donde hay un procedimiento externo que recibe parmetros de tipo "rbol" y luego invoca un procedimiento recursivo que realmente realiza el trabajo, y como argumento se le enva un puntero al nodo raz del rbol, como se muestra en Figura 4 con la funcin "Print0 ()" y el mtodo "Bin_Tree: Print ()". Esta forma de proceder no es conveniente porque induce al programador cliente a usar los campos privados del objeto, y as violentar el ocultamiento de datos que es el mecanismo que se usa para evitarle al programador cliente conocer cmo est implementado un mdulo de programacin. La abstraccin definida aqu permite implementar la funcin "Print ()" en trmino de sub-rboles, y sin usar una rutina intermedia como "Bin_Tree: Print ()" cuyo nico trabajo es invocar al procedimiento recursivo que realiza el trabajo. Por eso, la gran ventaja de esta especificacin del rbol es que permite manipular informacin organizada jerrquicamente,
ESTRUCTURAS DISCRETAS Pgina 19

pero evita el uso de punteros, que tanta dificultad representan para la mayor parte de los programadores.

ESTRUCTURAS DISCRETAS

Pgina 20

You might also like