                 La implementacin de los iteradores de tree.pas

                                    por

                                   Gabriela Castro B. 

GABRIELA CASTRO BORBON
CARNET 930944       

Resumen:
========

Se explica la implementacin de los siguientes iteradores del
rbol:

- Q_BF.pas
- Q_PLR.pas
- Q_LRP.pas
- Q_LPR.pas
- S_PLR.pas
- S_LRP.pas
- S_LPR.pas

Estos iteradores estn divididos en dos clases: los implementados
por medio de una cola (empiezan con Q) y los implementados por
medio de una pila (empiezan con S).

Primero que todo antes de comenzar con la explicacin de las
implementaciones es importante responder las siguientes
preguntas:



 QUE ES UN ITERADOR ?


Un iterador es modulo que encierra un recorrido a un tipo de
abstracto de datos; en el caso en que nos concierne un iterador
es un modulo que recorre de diferentes formas el tipo abstracto
Tree.pas.  

El iterador dentro de l se encarga de ir "caminando"  sobre el
rbol de la forma que indique su especificacin de tal manera que
si uno en determinado programa necesita hacer un recorrido solo
utiliza el iterador que lo contega.

Por ejemplo un iterador puede ser el que recorra el rbol por
niveles; osea camina sobre el primer nivel del rbol, sobre el
segundo nivel y as hasta llegar al ltimo nivel del rbol.  Si
uno en determinado programa necesita hacerle este mismo recorrido
al rbol no hara falta imlementarlo slo bastara utilizar el
iterador.

Lo nico que requieren estos iteradores es recordar la ley de
oro"Es incorrecto cambiar el valor del ADT contenedor mientras se
le recorre con un iterador. La gravedad de la falla que se
produzca depende mucho de la implementacin del iterador; en
algunos casos no  pasar nada, y en otros puede producirse un
error  fatal en tiempo de ejecucin "


CUALES SON LAS PARTES DE UN ITERADOR?

Es importante saber que todos los iteradores independientemente
del recorrido que realicen tienen el mismo nmero de
procedimientos de exportacin, osea procedimientos para el
usuario; pero pueden tener diferente nmero de procedimientos
locales.

Los procedimientos bsicos (los que utiliza el ususario)de cada
iterador son seis:

-Init
-Bind
-Next
-Current
-Finished
-Done


Init:
-----

Inicializa el iterador.
  * Inicializa todas las variables del rep del iterador, en
especial si este cuenta con memoria dinmica.
  * Si se usa el paquete de excepciones, al construir con Init()
el objeto tambin se le liga al  contexto de excepcin actual.  


Bind:
-----

Asocia al iterador  con el contenedor que recorrer, en este caso
con el rbol especifico.
  * Esta operacin es el prembulo necesario para recorrer por
medio del iterador el rbol.


Next:
-----

Retorna la posicin del siguente elemento del contenedor en el
orden definido en la especificacin  del iterador, osea si el
iterador recorre el rbol por niveles retornar el siguiente
elemento segn el nivel donde se encuentra.
Este procedimiento requiere que no se haya terminado de recorrer
el rbol y que el iterador ya haya  sido asociado a un contenedor
por  medio de la operacin Bind().

Current:
--------

Retorna el valor que la ltima invocacin a Next()  retorn.
  * Esta operacin nunca cambia el valor del iterador. 
  * Este procedimiento requiere que se haya invocado a la funcion
Next() antes de invocar a esta funcin.



Finished:
---------

Retorna TRUE cuando ya se ha terminado de recorrer el rbol (en
este caso especifico)  asociado al iterador, y FALSE cuando
todava quedan elementos por recorrer.
  * Si Finished() retorna FALSE, entonces todava es vlido
invocar a Next().
  * Esta operacin nunca cambia el valor del iterador. 
  * Este procedimiento requiere que el iterador haya sido
asociado a un contenedor por medio de la operacin Bind().
                                     


Done:
-----

Destruye totalmente al iterador "I".
  * En   general,  la  destruccin   de  un  objeto  consiste  en
devolverle al manejador de memoria dinmica toda la memoria
dinmica que usa, y cerrar sus  archivos.
  * El iterador  queda  inusable,  hasta el punto de que la nica 
manera de volverle a utilizar es reinicializndole   por medio de
Init().
  * Si se usa el paquete de excepciones, al  destruir   el objeto
tambin se le desliga de su contexto de  excepcin, por lo que si
se reinicializa de  nuevo  con Init() el resultado ser que quede
ligado  al  contexto  actual de  excepcin,  y no  al  que estaba 
anteriormente. 




 COMO SE UTILIZA UN ITERADOR ?


Hemos hablado de lo que es un iterador y de los seis
procedimientos que puede utilizar un programador usuario pero
ahora nos queda la duda de como utilizamos un iterador.

Para utilizar un iterador, por ser un modulo, no necesitamos
entender como est implementado por dentro, tan solo necesitamos
saber el tipo de recorrido que se le hace al contenedor y
entender bien las seis funciones antes explicadas.

Al utilizar un iterador uno debe invocar primero el init, y
despus el bind. Luego de haber invoacado estas dos operaciones
se invocan el next y el current (opcional) siempre y cuando el
finished no sea verdadero; cuando se termina de utilizar el
iterador se le hace un done para devolver toda la memoria
dinmica.

Para poder entender mejor esto, es importante ver un ejemplo
nmero 1 de la pgina siguinte; este pequeo ejemplo sirve para
mostrar cul es el estilo de programacin con que se usan los
iteradores:          
                                                                
- Lo usual es invocar a la operacin Next() del iterador
inmediatamente despus de que se entra al ciclo WHILE que est
resguardado por la invocacin a la funcin Finished().

- Si en el ciclo el programador, por la razn que  sea, necesita
conocer de nuevo el valor que Next()   retorn, puede recuperarlo
usando la operacin  Current().

- Como ocurre con los ADTs, a los interadores es  necesario
inicializarlos y destruirlos mediante  Init() y Done(). La mayor
parte de los iteradores  que son importantes requieren del uso de
memoria  dinmica, por lo que estas dos operaciones son
necesarias para asegurar el correcto desempeo del programa.

- En la especificacin de cualquier  iterador , las operaciones
se definen con  la siguiente cadena de requisitos para invocar a
cada operacin del iterador:


   Init()+-->Bind()-->Finished()-->Next()-->Current()
         |
         +-->Done()                                               

              
El programador usuario del iterador debe respetar todos estos
requisitos, pues si no lo hace su programa estar incorrecto.


- Como todos los iteradores usan exactamente las  mismas
operaciones, el programador usuario del  iterador debe calificar
cada operacin con el  nombre de la unidad en que se usa el
iterador.

- En la especificacin de las operaciones de los  iteradores no
se menciona cul es el contenedor que se recorre. Estas
especificaciones han sido redactadas a propsito de esta manera,
pues  independientemente de cul sea el contenedor, la  
especificacin del iterador siempre es la misma. Lo nico que
vara es la clusula ORDEN, en donde se  define cul es el orden
en que se recorre al ADT contenedor.


EJEMPLO 1


ͻ 
PROCEDURE Proc;            { EXPORT }   { ADH }                
  {+} VAR C: TContainer    { contenedor a procesar }           
;                                                              
 RESULTADO                                                     
 Este procedimiento usa el iterador "I" para recorrer          
 el ADT Contenedor "C" y aplicarle a cada uno de sus           
 elementos un proceso                                          
 Procese(). }                                                  
{ Modificaciones por Gabriela Castro}                          
VAR                                                            
  I    : Itertor;    { iterador para recorrer C }              
                                                               
  p,q  : PCpos;      { posicin en el contenedor }             
                                                               
  { ... }            { otras variables... }                    
                                                               
  n  : WORD;                                                   
BEGIN { Proc }                                                 
 { inicializa el iterador }                                    
 Iterator.Init(I);                                             
 { ... }                                                       
                                                               
 { liga el iterador al contenedor }                            
 Iterator.Bind(I,C);                                           
 WHILE NOT Iterator.Finished(I) DO BEGIN                       
   { avanza el iterador }                                      
   p  := Iterator.Next(I);                                     
                                                               
   { ... }                                                     
   Procesa p                                                   
   { ... }                                                     
   q  := Iterator.Current(I);                                  
   { ... }                                                     
   Procesa q (opcional no es necesario llamar a Current)       
   {..... }                                                    
 END;                                                          
 { ... }                                                       
                                                               
 { usa de nuevo el mismo iterador }                            
 n := 0;                                                       
 Iterator.Bind(I,C);                                           
 WHILE NOT Iterator.Finished(I) DO BEGIN                       
   INC(n);                                                     
   p:= Iterador.Next(I);                                       
   Procesa a p                                                  
 END;                                                          
                                                               
 { destruye al iterador }                                      
 Iterator.Done(I);                                             
ͼ 

 CUAL ES LA VENTAJA DE USAR ITERADORES?


La principal ventaja de usar iteradores es que uno no debe
reprogramar cada vez que desee utilizar o hacer cierto tipo de
recorrido al contenedor, simplemente debe saber usarlos pero como
pudo usted darse cuenta cualquier persona es capaz de usarlos
pues no debe entender su implementacin.  Otra ventaja importante
de estos tipos de mdulos es la reutilizacin del cdigo pues
mientras que Adolfo Di Mare se pasa horas programandolos, cientos
de sus estudiantes nos ahorramos todo ese tiempo a la hora de
hacer nuestros programas.






IMPLEMENTACION DE LOS ITERADORES DE TREE.PAS
============================================


Despus de responder todas las preguntas lgicas que uno se hace
de inmediato cuando le mencionan la palabra iterador; es adecuado
empezar ya con nuestro trabajo primordial: la explicacin de
siete iteradores del rbol.  Como mencion al principio del
documento estos iteradores se dividen en dos tipos los de cola y
los de pila; como cada tipo lleva un patrn de programacin
parecido los explicare en grupos. 




IMPLEMENTACION DE LOS ITERADORES DE COLA
----------------------------------------


Los iteradores de la cola son cuatro:


-Q_BF
-Q_LRP
-Q_LPR
-Q_PLR



Los cuatro poseen igual estructura: en el bind se llena la cola
con los elementos del rbol en el orden que indica cada iterador
y en las dems funciones los cuatro son exactamente iguales por
lo que explicare el recorrido y el bind de cada iterador por
separado y despus explicar los restantes cinco procedimientos
juntos pus no hay diferencia alguna entre ellos. 

Q_BF:
-----

Este iterador permite recorrer el ADT Arbol  por niveles,
comenzando por el nivel superior hasta llegar a las hojas, el
orden que lleva en cada nivel es de izquierda a derecha.  Este
recorrido es el que usa en la bsqueda Breadth-First.

  Para el siguiente rbol:


                             a
                            /|\
                          / / \ \
                         b  c d  e
                        /|\     /|\
                       f g h   i j k
                                / \
                                l m


el orden de recorrido que resulta al usar este iterador es
[a,b,c,d,e,f,g,h,i,j,k,l,m].   

Este iterador SI accesa los campos del Rep de TTree. Esto quiere
decir que este iterador debe ser reprogramado si se usa una
implementacin  diferente de TTree. 




El rep de este iterador es el siguiente:
                 


{[])=====================================([]}
{[])  IMPLEMENTATION                     ([]}
{[])=====================================([]}
{[]}  TYPE                               {[]}
{[]}                                     {[]}
{[]}    Rep_BF  = RECORD                 {[]}
{[]}      _queue: TPList;                {[]}
{[]}      _c    : PTpos;  { Current(I) } {[]}
{[]}      {$IFDEF USE_Except }           {[]}
{[]}        _excp: TException;           {[]}
{[]}      {$ENDIF USE_Except }           {[]}
{[]}    END;                             {[]}
{[]}                                     {[]}
{[]}    I_BF = RECORD                    {[]}
{[]}      Rep : Rep_BF;                  {[]}
{[]}    END;                             {[]}
{[]}====================================={[]}



I.Rep._queue es una cola que contiene los punteros  a todos los
nodos del rbol. Para llenar la cola, el  procedimiento Bind()
recorre el rbol por niveles y  agrega cada nodo al campo _queue
que es una cola; al ejecutar el bind la cola queda llena por
completa. De tal forma el Next() se limita a sacar el primer
elemento de la  cola(borrandolo despus), para luego devolverlo.

La cantidad de memoria dinmica que usa el  iterador es
O(Count(T)).

La idea general es recorrer el rbol una nica vez. El iterador
lo que hace es crear una cola de los nodos que debe devolver, es
decir, el iterador crea una lista cuando se invoca al
procedimiento BIND y la deja preparada para ser devuelta. Lo que
se hace  para lograr esto, es implementar el siguiente algoritmo,
en la funcin BIND que es la que sufre un  cambio significativo,
las dems operaciones se  mantienen  dentro de un patrn definido
para los iteradores de cola.

ALGORITMO

  1. Si el rbol no est vaco, inserte al final de la cola
(I.Rep._queue) la raz del rbol.
  2. Coloque un puntero "P" al primer nodo de la cola( en este
caso a la raz).
  3. Inserte al final de la cola, uno por uno, todos los hijos
del nodo que es apuntado por "P" en el orden en que aparecen.
  4. Avance "P", y regrese al paso 3.
  5. Detngase cuando ya haya recorrido toda la cola.

As nos aseguramos de que la insercin se hace por niveles, y de
izquierda a derecha, as el rbol se recorre una sola vez y se
obtienen los nodos a los  que debemos colocar punteros
pertenecientes a la  cola.

         La idea del recorrido es la siguiente:

           Q                 Ŀ
                                                   
       p1  >  a     
       p2  Ŀ           
       p3        > b    c  <
       p4  Ŀ  ٳ      
       .                          > d  e  f   ghi
       .                                        
       .                                      j  k l<
       p12  

       p13  >  NULL



Como p13 es Null entonces se detiene, y Bind() termina.

Cada p representa un llamado hecho desde un WHILE que se
encuentra en un Bind(). En el diagrama se llama p#
correspondiente al Next() de p iniciando con la raz. Q es la
cola, o sea, es I.Rep._queue y se presenta como va aumentando el
nmero de nodos de  la cola.



Q_LRP:
------

Este iterador permite recorrer el ADT Arbol en PosOrden (
izquierda, derecha, padre) de ah proviene su nombre.


  Para el siguiente rbol:

                             a
                            /|\
                          / / \ \
                         b  c d  e
                        /|\     /|\
                       f g h   i j k
                                / \
                                l m

el orden de recorrido que resulta al usar este iterador es
[f,g,h,b,c,d,i,l,m,j,k,e,a]. 

Este iterador SI accesa los campos del Rep de TTree. Esto quiere
decir que este iterador debe ser reprogramado si se usa una
implementacin  diferente de TTree. 

El rep de este iterador es el siguiente:


{[])=====================================([]}
{[])  IMPLEMENTATION                     ([]}
{[])=====================================([]}
{[]}  TYPE                               {[]}
{[]}                                     {[]}
{[]}    Rep_LRP = RECORD                 {[]}
{[]}      _queue: TPList;                {[]}
{[]}      _c    : PTpos;  { Current(I) } {[]}
{[]}      {$IFDEF USE_Except }           {[]}
{[]}        _excp: TException;           {[]}
{[]}      {$ENDIF USE_Except }           {[]}
{[]}    END;                             {[]}
{[]}                                     {[]}
{[]}    I_LRP = RECORD                   {[]}
{[]}      Rep : Rep_LRP;                 {[]}
{[]}    END;                             {[]}
{[]}                                     {[]}
{[])=====================================([]}

I.Rep._queue es una cola que contiene los punteros a todos los
nodos del rbol. Para llenar la cola, el procedimiento recursivo
Bind0() recorre el rbol en LRP y le agrega cada nodo a la cola.
Next() se  limita a sacar el primer elemento de la cola, para
luego devolverlo.

La cantidad de memoria dinmica que usa el iterador  es
O(Count(T)).

La idea general es recorrer el rbol una nica vez. El iterador
lo que hace es crear una cola de los nodos que debe devolver, es
decir,  el  iterador  crea  una  lista   cuando  se  invoca   al
procedimiento BIND y la deja preparada para ser devuelta. Lo que
se hace  para lograr esto, es implementar el siguiente algoritmo,
en la funcin BIND que es la que sufre un  cambio significativo,
las dems operaciones se  mantienen  dentro de un patrn definido
para los iteradores de cola.


ALGORITMO

  1. Si el rbol no est vaco se coloca en el hijo que se
encuentra ms a la izquierda: esto lo hace preguntando
recursivamente cual es el primer hijo del primer hijo, etc; hasta
encontrar un nodo cuyo primer hijo es nulo, eso indica que ese
nodo en el que se encuentra es el hijo que se encuentra ms a la
izquierda en el rbol por lo que se inserta.

Ejemplo
                             a
                            /|\
                          / / \ \
                         b  c d  e
                        /|\     /|\
                       f g h   i j k
                                / \
                                l m

En este ejemplo especifico se pregunta por el primer hijo de la
raiz que es 'b'; como b es diferente de nulo se pregunta por el
primer hijo de 'b' que es 'f'; como 'f' es diferente de nulo se
pregunta por su primer hijo que es nulo; esto implica que 'f' es
el hijo que se encuentra ms a la izquierda de este rbol por lo
que se inserta.

I.rep.queue := [f]  {estado actual de la cola}

  2. En el momento en que se inserta el hijo ms izquierdo se
pregunta por su hermano derecho.  Si existe un hermano derecho se
repite el proceso '1' y '2' y sino existe hermano derecho se
inserta el padre y se pregunta por su hermano derecho
repitiendose una y otra vez el proceso '1' y '2'.  Lo ltimo que
se inserta sera la raz.

Ejemplo

                            
                             a
                            / \
                          /   \ \
                         b    d  e
                        /|    
 > f g    c
                               




I.rep.queue := [f]  {estado actual de la cola}

En este ejemplo ya que se inserto el hijo ms izquierdo
pregunatariamos si posee hermano derecho como si posee hermano
derecho preguntamos por su hijo colocado ms a su izquierda que
en este caso sera el mismo 'g' por lo que lo inserta


             *
                            a
                           / \
                         /   \ \
                        b    d  e
                       /|    
                      f g    c
                           
                        
             


I.rep.queue := [f g ] {estado actual de la cola}


Ahora se pregunta por su hermano derecho pero como no tiene se
sube al padre y se inserta.

             
             
             
                            a
                           / \
                         /   \ \
             >  b    d  e
                        /|    
                       f g    c
                            


I.rep.queue := [f g b ]


Ahora se pregunta por su hermano derecho que sera 'd':

             
             
                            a
                           / \
                         /   \ \
                        b   d  e
                       /|   
                      f g   c
                           
             



Como es diferente de nulo se pregunta por su primer hijo que es
'c'


             
             
                            a
                           / \
                         /   \ \
                        b    d  e
                       /|    
                      f g   c
                           
             


Ahora se pregunta por su primer hijo pero como es nulo entoces se
inserta 'c'

I.rep.queue := [f g b c ] {estado actual de la cola}



Despus que se inserta se pregunta por su hermano derecho y como
no tiene entonces se inserta el padre


             
             
                            a
                           / \
                         /   \ \
                        b   d  e
                       /|   
                      f g   c
                           
             



Ahora se pregunta por el hermano derecho de 'd' que es 'e'.  Como
es diferente de nulo se pregunta por su primer hijo pero como
este no exite se inserta 'e'

             
             
                            a
                           / \
                         /   \ \
                        b    d  e
                       /|       
                      f g    c  
                                
             


Ahora se pregunta por el hermano derecho de 'e' y como es nulo se
inserta su padre 'a'


             
             
                
             >a
                            / \
                          /   \ \
                         b    d  e
                        /|    
                       f g    c
                            





Q_LPR:
------


Este iterador permite recorrer el ADT Arbol en InOrden (
izquierda, padre, derecha)



Para el siguiente rbol:

                             a
                            /|\
                          / / \ \
                         b  c d  e
                        /|\     /|\
                       f g h   i j k
                                / \
                                l m

el orden de recorrido que resulta al usar este iterador es
[f,b,g,h,a,c,d,i,e,l,j,m,k]. 


Este iterador SI accesa los campos del Rep de TTree. Esto quiere
decir que este iterador debe ser  reprogramado si se usa una
implementacin  diferente de TTree. 



El rep de este iterador es:



{[])=====================================([]}
{[])  IMPLEMENTATION                     ([]}
{[])=====================================([]}
{[]}  TYPE                               {[]}
{[]}                                     {[]}
{[]}    Rep_LPR = RECORD                 {[]}
{[]}      _queue: TPList;                {[]}
{[]}      _c    : PTpos;  { Current(I) } {[]}
{[]}      {$IFDEF USE_Except }           {[]}
{[]}        _excp: TException;           {[]}
{[]}      {$ENDIF USE_Except }           {[]}
{[]}    END;                             {[]}
{[]}                                     {[]}
{[]}    I_LPR = RECORD                   {[]}
{[]}      Rep : Rep_LPR;                 {[]}
{[]}    END;                             {[]}
{[]}                                     {[]}
{[])=====================================([]}



I.Rep._queue es una cola que contiene los punteros a todos los
nodos del rbol. Para llenar la cola, el procedimiento recursivo
Bind0() recorre el rbol en  LPR y le agrega cada nodo a la cola.
Next() se  limita a sacar el primer elemento de la cola, para
luego devolverlo.


La cantidad de memoria dinmica que usa el iterador es
O(Count(T)).


La idea general es recorrer el rbol una nica vez. El iterador
lo que hace es crear una cola de los nodos que debe devolver, es
decir,  el  iterador  crea  una  lista   cuando  se  invoca   al
procedimiento BIND y la deja preparada para ser devuelta. Lo que
se hace  para lograr esto, es implementar el siguiente algoritmo,
en la funcin BIND que es la que sufre un  cambio significativo,
las dems operaciones se  mantienen  dentro de un patrn definido
para los iteradores de cola.

ALGORITMO:
----------

El recorrido  que realiza el iterador en el procedimiento Bind lo
hace empleando recursividad;  este procedimiento lo que hace es
llamar a un Bind0 que es recursivo.  Este Bind0 se divide en tres
partes : la primera procesa el subrbol izquierdo, despus de
haberlo introducido todo, procesan al padre por ltimo procesan
al subrbol derecho.

Para procesar elsubrbol izquierdo recursivamente va preguntando
por el primer hijo de cada nodo hasta llegar al descendiente  ms
izquierdo de la raz.  Cuando est ubicado en este nodo lo
introduce a la cola, despus introduce al padre y por litmo
procesa a sus hermanos derechos.

Para procesar los hermanos derechos se coloca en el siguiente
hermano y comienza de nuevo a procesarlo como si fuera un rbol
independiente; osea procesa su subrbol izquierdo, despus el
nodo y por ltimo el subrbol derecho aas recursivamente hasta
agotar el rbol.


Para poder entenderlo mejor vemos un ejemplo pequeo:


        [a]
       /   \
    [b]     [c]
    / \     / \
  [d] [e] [f] [g]


En este rbol lo dividimos en tres partes 



Subrbol izquierdo            Padre        Subrbol derecho


    [b]                       [a]                 [c]
    / \                                           / \
  [d] [e]                                       [f] [g]

  rbol "B"                  nodo "a"          rbol "c"


Como dice el algoritmo primero se procesael subrbol izquierdo
(osea el rbol "b").  Si tomamos el rbol "b" y lo dividimos en
tres partes de nuevo quedara de la siguiente forma:

Subrbol izquierdo            Padre        Subrbol derecho

      [d]                      [b]               [e]

Ahora procesamos primero el subrbol izquierdo pero como este es
solo un nodo lo metemos a la cola de tal forma que la cola queda
as:
I.rep.queue:= [d]

Ahora introducomos el padre:

I.rep.queue:= [ d b ]

Ahora procesamos el subrbol derecho pero como tambin es un nodo
lo que hacemos es introducirlo a la cola:

I.rep.queue:= [ d b e ]


Como podemos observar ya est procesado todo el subrbol
izquierdo del rbol original osea todo el rbol "b" ;  ahora como
dice el algoritmo procesamos el padre (nodo "a"):

I.rep.queue:= [ d b e a ]



Despus de procesar el padre procesamos el subrbol drecho osea
el rbol "c".   Si tomamos el rbol "c" y lo dividimos en tres
partes de nuevo quedara de la siguiente forma:

Subrbol izquierdo            Padre        Subrbol derecho

      [f]                      [c]               [g]



Ahora procesamos primero el subrbol izquierdo pero como este es
solo un nodo lo metemos a la cola de tal forma que la cola queda
as:
I.rep.queue:= [d b e a f]

Ahora introducomos el padre:

I.rep.queue:= [ d b e a f c]

Ahora procesamos el subrbol derecho pero como tambin es un nodo
lo que hacemos es introducirlo a la cola:

I.rep.queue:= [ d b e a f c g]


Como podemos observar ya procesamos las tres partes del rbol
oroginal y qued dentro de la cola en la forma LPR;  pero cabe
aclarar que este ejemplo solo explica un poco el sistema del
algoritmo en s;  pero en realidad o graficamente el algoritmo no
divide el rbol en tres partes como se hace en este ejemplo sino
que el algoritmo como trabaja recursivamente va dejando punteros
en lugares especficos de tal forma que cuando regresa procesa
primero todo el subrbol izquierdo, despus el padre y de ltimo
todo el subrbol derecho parecido a la forma en que este ejemplo
trata de explicarlo.




Q_PLR:
------

Este iterador permite recorrer el ADT Arbol en PreOrden ( padre,
izquierda, derecha ).

Para el siguiente rbol:


                             a
                            /|\
                          / / \ \
                         b  c d  e
                        /|\     /|\
                       f g h   i j k
                                / \
                                l m

el orden de recorrido que resulta al usar este iterador es
[a,b,f,g,h,c,d,e,i,j,l,m,k]. 

Este iterador SI accesa los campos del Rep de TTree. Esto quiere
decir que este iterador debe ser  reprogramado si se usa una
implementacin   diferente de TTree. 

El rep de este iterador es:


{[])=====================================([]}
{[])  IMPLEMENTATION                     ([]}
{[])=====================================([]}
{[]}  TYPE                               {[]}
{[]}                                     {[]}
{[]}    Rep_PLR = RECORD                 {[]}
{[]}      _queue: TPList;                {[]}
{[]}      _c    : PTpos;  { Current(I) } {[]}
{[]}      {$IFDEF USE_Except }           {[]}
{[]}        _excp: TException;           {[]}
{[]}      {$ENDIF USE_Except }           {[]}
{[]}    END;                             {[]}
{[]}                                     {[]}
{[]}    I_PLR = RECORD                   {[]}
{[]}      Rep : Rep_PLR;                 {[]}
{[]}    END;                             {[]}
{[]}                                     {[]}
{[])=====================================([]}

I.Rep._queue es una cola que contiene los punteros a todos los
nodos del rbol. Para llenar la cola, el procedimiento recursivo
Bind0() recorre el rbol en PLR y le agrega cada nodo a la cola.
Next() se limita a sacar el primer elemento de la cola, para
luego devolverlo.


La cantidad de memoria dinmica que usa el iterador es
O(Count(T)).


La idea general es recorrer el rbol una nica vez. El iterador
lo que hace es crear una cola de los nodos que debe devolver, es
decir,  el  iterador  crea  una  lista   cuando  se  invoca   al
procedimiento BIND y la deja preparada para ser devuelta. Lo que
se hace  para lograr esto, es implementar el siguiente algoritmo,
en la funcin BIND que es la que sufre un  cambio significativo,
las dems operaciones se  mantienen  dentro de un patrn definido
para los iteradores de cola.





ALGORITMO:
----------



1.  Si el rbol no est vaco:  P es igual a la raz 

2.  Introduce a "p" dentro de la cola 

3.  Pone en pL al primer hijo de "p"

    a.  Si pL es diferente de nulo "p" lo iguala con pl y se      
    devuelve al punto "2".

    b.  Si pL es nulo   entonces  pL lo iguala  al siguiente      
    hermano de "p" y p lo iguala con el padre de p (siempre y     
    cuando p no sea la raz) y se devuelve al punto 3a  3b       
    dependiendo del valor de pL hasta que p sea igual a la raz y 
    pL = nulo.



Con este algorimo sucede lo mismo que con el iterador anterior
que es una forma clara de explicar lo que hace el iterador en el
Bind pero no es exactamente lo mismo que tiene escrito el
procedimiento; debido a que como este es recursivo no necesita
por ejemplo igualar a p con el padre porque tan solo al
devolverse recursivamente los punteros estn ya colocados; la
idea es que difiere en detalles pero me parece que es muy claro
explicar el algoritmo de est forma.

Vemos funcionar el algoritmo con un ejemplo pequeo:


        [a]
       /   \
    [b]     [c]
    /
   [e]






Segn el algorimo p es igual a la raz:


p ----> [a]
       /   \
    [b]     [c]
    /
   [e]

Introducimos p a la cola:   I.rep.queue:= [a]




Ahora pL es igual al primer hijo de p.  Como pL es [b] diferente
de nulo entonces p lo igualamos a pL.

            [a]
           /   \
p -----> [b]   [c]
         /
       [e]

Introducimos p a la cola:  I.rep.queue:= [a b]




Ahora pL es igual al primer hijo de p.  Como pL es [e] diferente
de nulo entonces p lo igualamos a pL.
     
                  [a]
                 /   \
              [b]     [c]
              /
p -------->  [e]

Introducimos p a la cola:  I.rep.queue:= [a b e]


Ahora pL es el primer hijo de p osea de "e" pero como no posee
(como pL es nulo) entonces PL es igual al siguiente hermano de P
y p es el padre de p; osea los punteros estarn de la siguiente
forma:

            [a]
           /   \
p -----> [b]   [c]
         /
       [e]  nil <----- pL


Como PL es nulo.  Segn el algoritmo de nuevo PL es igual al
siguiente hermano de P y p es el padre de p osea [a]


p ----->    [a]
           /   \
         [b]   [c]   <---- pL
         /
       [e]  

Como p es la raz pero pL es diferente de nulo continuamos con el
algoritmo.  Ahora p es pL y lo introduce al cola:

I.rep.queue := [a b e c]


Despus de esto pl es igual al primer de p osea al primer hijo de
[c] que es nulo.  Como PL es nulo y p es la raz entonces termina
el recorrido.





PROCEDIMIENTOS   COMUNES   PARA  LOS  ITERADORES   DE  TREE.PAS
IMPLEMENTADOS POR  MEDIO  DE COLAS


Como dije anteriormente en la parte superior del documento los
iteradores de Tree.pas implementados por medio de colas posee una
estructura similar: el bind crea una cola con todos los elementos
que deben ser devueltos; esto implica que el bind es el que sufre
los cambios significativos por lo que los otros cinco
procedimientos son exactamente iguales para los iteradores;debido 
a esto los voy a explicar juntos:


El puntrero comn que poseen todos los iteradores I.rep.c lo que
seala es el elemento anterior que se mand osea el ltimo next
(el current)


Init:
-----

Como la unica variable que utiliza memoria dinmica es
I.rep.queue; init lo que hace es inicializarla.


Done:
-----

Destruye la cola: I.rep.queue.


Next:
-----

Este procedimiento lo que hace es sacar el primero de la cola,
ese es el valor que devuelve , y actualiza I.rep.c;  de tal forma
que I.rep.c es igual a next.

Finished:
---------

El iterador termina su recorrido cuando la cola est  vaca.



Current:
--------

Retorna el valor de la ltima invocacin a next por lo que
current es igual a I.rep.c.







IMPLEMENTACION DE LOS ITERADORES DE PILA
----------------------------------------


Los iteradores de pila son cuatro:


1.  S_LRP
2.  S_PLR
3.  S_LPR  (con una pila)


Estos iteradores son muy complejos pues en lugar de trabajar con
una cola, trabajan con una pila; si recordamos las
caracteristicas del pila el primer elemento que se introduce en
ella es el ltimo que sale y el ltimo que se mete es el primero
que sale por lo que su implementacin es complicada de entender;
pero con esta breve explicacin se le har muy fcil entender el
manejo de como estn implementados.



S_LRP:
------

Este iterador permite recorrer el ADT Arbol en PosOrden (
izquierda, derecha, padre)


Para el siguiente rbol:

                             a
                            /|\
                          / / \ \
                         b  c d  e
                        /|\     /|\
                       f g h   i j k
                                / \
                                l m

el orden de recorrido que resulta al usar este iterador es
[f,g,h,b,c,d,i,l,m,j,k,e,a]. 

Este iterador SI accesa los campos del Rep de TTree. Esto quiere
decir que este iterador debe ser reprogramado si se usa una
implementacin  diferente de TTree. 

  
El rep de este iterador es:

{[])=====================================([]}
{[])  IMPLEMENTATION                     ([]}
{[])=====================================([]}
{[]}  TYPE                               {[]}
{[]}                                     {[]}
{[]}    Rep_LRP = RECORD                 {[]}
{[]}      _stack: TPList;                {[]}
{[]}      _T    : PTree;  { Contenedor } {[]}
{[]}      _c    : PTpos;  { Current(I) } {[]}
{[]}      {$IFDEF USE_Except }           {[]}
{[]}        _excp: TException;           {[]}
{[]}      {$ENDIF USE_Except }           {[]}
{[]}    END;                             {[]}
{[]}                                     {[]}
{[]}    I_LRP = RECORD                   {[]}
{[]}      Rep : Rep_LRP;                 {[]}
{[]}    END;                             {[]}
{[]}                                     {[]}
{[])=====================================([]}

I.rep.stack es la pila que va a estar como gua, no va a poseer
todos los elementos a regresar como lo haca la cola sino va a
poseer unos cuantos que sirven para ir tomando los otros.  La
pila se est actualizando constantemente.


I.rep.T es un puntero al rbol que se va a recorrer.

I.rep.c es el ltimo valor que regreso next osea sirve como
current.



La idea de este iterador es mantener en el tope de la pila el
proximo elemento a mandar segun el orden establecido por medio
del siguiente algorimo:



**  Si el rbol no est vaco mete en la pila todos los
descendientes izquierdos de la raz; empezando desde la raz
misma; osea esta es la primera en ser introducida en la pila (por
las caractersticas de la pila ser la ltima que se saque),
despus se van introduciendo todos sus descendientes izquierdos
por orden de niveles.


Ejemplo



       [1]      Ŀ
      /   \     @1
    [2]   [7]   @2
    / \         @3 < Top
  [3] [4]
      /
     [5] 
     / 
   [6]   



NOTA:
      La pila se dibuja de cabeza para seguir con las
convenciones de Di Mare al dibujarlo dentro del iterador; el
escribe que lo hace de esta forma para que sea   sencillo ver la
correspondencia que hay entre los punteros de la pila y la rama
del rbol que se  guarda en la pila.



**  Next lo que saca es el tope de la pila e introduce en ella el
hermano derecho y toda su descendencia izquierda.  


Ejemplo:


       [1]      Ŀ             Ŀ 
      /   \     @1             @1 
    [2]   [7]   @2             @2 
    / \         @3 < Top     @4 
  [3] [4]                        @5 
      /                          @6 <  Top
     [5]                              
     / 
   [6]   


**  Si el tope no tiene hermano derecho no introduce nada en la
pila, porque eso quiere decir que ya recorri toda la
descendencia izquierda y derecha por lo que el prximo es el tope
que ya est colocado en la pila osea el padre de la descendencia
ya mandada.

Ejemplo:


       [1]      Ŀ             Ŀ            Ŀ   
      /   \     @1             @1             @1   
    [2]   [7]   @2             @2             @2   
    / \         @3 < Top     @4             @4   
  [3] [4]                        @5             @5 < Ŀ
      /                          @6  <  Top           
     [5]                                                  
     /                                                   Top
   [6]   




Como 6 no tiene hermano derecho no se introduce nada en la pila
por lo que el prximo a sacar es el 5.




**  Este proceso se continua haciendo hasta que la pila quede
totalmente vaca.




Este algoritmo no se recarga en un solo procedimiento como
sucedia con los iteradores implementados por medio de cola sino
que se recarga en dos procedimientos: el Bind y el Next. A
continuacin la explicacin breve de la implementacin de los
seis procedimientos del iterador.

Init:
-----

Inicializa la pila, con la funcin de Init de de la unidad Plist.



Bind:
-----

Conecta el iterador con el rbol por medio del puntero I.rep.T;
limpia la pila y le mete a todos los descendientes izquierdos
de la raz

Ejemplo:


       [1]      Ŀ
      /   \     @1
    [2]   [5]   @2
    / \         @3 < Top
  [3] [4]



Done:
-----

Destruye la pila, con la funcin de Done de de la unidad Plist.



Next:
-----
Regresa  el prximo  elemento  del arbol, de acuerdo  a  la 
estructura I_D_P . Coloca  dentro  de la pila  los elmentos
prximos a sacar . Por  Ejemplo de los valores que se almacena en
I.Rep_.stack  despus de la invocacin inical a Bind(), y despus
de invocar a Next().


       [1]      Ŀ  Ŀ
      /   \     @1  @1  Ŀ
    [2]   [5]   @2  @2  @1  Ŀ
    / \         @3  @4  @5  @1  Ŀ  < top
  [3] [4]
               Bind() Next()...


RESULTADO del recorrido en I_P_D:

     [ 3 4 2 5 1 ]


Siempre el prximo a retornar es el  que est de primero en la
pila; y despus reacomoda la pila para que quede arriba el que
hay que regresar la prxima vez; osea si posee hermano derecho
introduce toda su descendencia izquierda a la pila.

Este procedimiento lo que hace es retirar el elemento Tope de la
pila y actualiza I.rep.c de tal forma que sea igual a Next



Finished:
---------

Regresa True cuando la pila est vaca.


Current:
--------

Retorna el ltimo valor regresado por Next que en este caso es
I.rep.c






S_PLR:
-----

Este iterador permite recorrer el ADT Arbol en PreOrden (padre,
izquierda, derecha)


Para el siguiente rbol:



                             a
                            /|\
                          / / \ \
                         b  c d  e
                        /|\     /|\
                       f g h   i j k
                                / \
                                l m


el orden de recorrido que resulta al usar este iterador es
[a,b,f,g,h,c,d,e,i,j,l,m,k]. 

Este iterador SI accesa los campos del Rep de TTree. Esto quiere
decir que este iterador debe ser  reprogramado si se usa una
implementacin  diferente de TTree. 

El rep de este iterador es:


{[])=====================================([]}
{[])  IMPLEMENTATION                     ([]}
{[])=====================================([]}
{[]}  TYPE                               {[]}
{[]}                                     {[]}
{[]}    Rep_PLR = RECORD                 {[]}
{[]}      _stack: TPList;                {[]}
{[]}      _T    : PTree;  { Contenedor } {[]}
{[]}      _c    : PTpos;  { Current(I) } {[]}
{[]}      {$IFDEF USE_Except }           {[]}
{[]}        _excp: TException;           {[]}
{[]}      {$ENDIF USE_Except }           {[]}
{[]}    END;                             {[]}
{[]}                                     {[]}
{[]}    I_PLR = RECORD                   {[]}
{[]}      Rep : Rep_PLR;                 {[]}
{[]}    END;                             {[]}
{[]}                                     {[]}
{[])=====================================([]}



I.rep.stack es la pila que va a estar como gua, no va a poseer
todos los elementos a regresar como lo haca la cola sino va a
poseer unos cuantos que sirven para ir tomando los otros.  La
pila se est actualizando constantemente.


I.rep.T es un puntero al rbol que se va a recorrer.


I.rep.c es el ltimo valor que regreso next osea sirve como
current.


La idea de este iterador es mantener en el tope de la pila el
proximo elemento a mandar segun el orden establecido por medio
del siguiente algorimo:


**  Si el rbol no est vaco introduce a la pila la raz

**  Next lo que hace es sacar el tope de la pila y pone un
puntero al primer hijo:


   -Si  su primer hijo es diferente de nulo entonces introduce a  
   la pila al tope (de nuevo)  junto con su primer hijo.

   -Si su primer hijo es nulo osea no existe toma a su hermano    
   derecho:

       Si el hermano derecho existe lo inserta en la pila

       Si no existe entonces saca el siguiente de la pila y      
       pregunta si tiene hermano derecho:


           Si tiene se introduce en la pila.

           Sino tiene hermano derecho se debe sacar el padre de  
           la pila y repetir el proceso (de preguntar si posee    
           hermano derecho)  hasta encontrar un hermano derecho o 
           que la pila quede totalmente vaca.
            
       
      

Para poder entender mejor este algoritmo vemolo por medio de un
ejemplo:



               [a]
              /  \
             /    \  
            [b]   [c]
            / \    /
          [d] [e] [f]
                  / 
                 [g]   
    

Como dice el algoritmo el rbol no est vaco se introduce la
raz a la pila


Ŀ  
@a <  Top
    


Cuando se invoca el primer next lo que hace es sacar el tope de
la pila y como dice el algorimo se pone un puntero al primer hijo
como este es diferente de nulo se introduce de nuevo el tope
junto con su primer hijo:
        

Ŀ  
@a  
@b < Top
      
    
En el prximo next se saca @b y se coloca un puntero a su primer
hijo como este es diferente de nulo se introduce de nuevo el tope
junto con su primer hijo:

Ŀ  
@a  
@b
@d < Top
    


En el prximo next se saca @d y se coloca un puntero a su primer
hijo como no existe entonces toma a su hermano derecho. Como este
es diferente de nulo osea exite entonces lo introduce a la pila

Ŀ  
@a  
@b
@e < Top
    


En el prximo next se saca @e;{ al sacar @e la pila queda de la
siguiente forma

Ŀ  
@a  
@b < Top    }



y se coloca un puntero a su primer hijo como no existe entonces
toma a su hermano derecho. Como este tampoco existe entonces
entonces saca el siguiente de la pila osea @b y pregunta por du
hermano derecho que es @c y lo introduce a la pila

Ŀ  
@a  
@c < Top     



En el siguiente next saca la direccin de "c" y pregunta por su
primer hijo (@f) como este es diferente de nulo; introduce a la
pila a @c de nuevo junto con su primer hijo


Ŀ  
@a  
@c
@f < Top
    


En el siguiente next saca la direccin de "f" y pregunta por su
primer hijo (@g) como este es diferente de nulo; introduce a la
pila a @f de nuevo junto con su primer hijo "g"

Ŀ
@a  
@c
@f
@g< Top
    

El siguiente next saca a "g" y pregunta por su primer hijo como
es nulo, pregunta por su hermano derecho,  como tampoco existe 
saca el siguiente de la pila; osea "f" y pregunta por su hermano
derecho; pero como tampoco tiene saca al siguiente de la pila que
es "c" y pregunta por su hermano derecho; pero como tampoco posee
hermano derecho  saca al siguiente de la pila que es "a" y
pregunta por su hermano derecho que tampoco posee y como la pila
ya est vaca termina el recorrido del iterador.


Si observamos el recorrido que el iterador  realiz fue  el
siguiente:

[ a b d e c f g ] 

y efectivamente ese es el recorrido PLR.



S_LPR:
------


Este iterador permite recorrer el ADT Arbol en InOrden (
izquierda, padre, derecha)

Para el siguiente rbol:

                             a
                            /|\
                          / / \ \
                         b  c d  e
                        /|\     /|\
                       f g h   i j k
                                / \
                                l m

el orden de recorrido que resulta al usar este iterador es
[f,b,g,h,a,c,d,i,e,l,j,m,k]. 

Este iterador SI accesa los campos del Rep de TTree. Esto quiere
decir que este iterador debe ser  reprogramado si se usa una
implementacin   diferente de TTree. 


El rep de este iterador es:


{[])=====================================([]}
{[])  IMPLEMENTATION                     ([]}
{[])=====================================([]}
{[]}  TYPE                               {[]}
{[]}                                     {[]}
{[]}    Rep_LPR = RECORD                 {[]}
{[]}      _stack : TPList;               {[]}
{[]}      _T     : PTree; { Contenedor } {[]}
{[]}      _c     : PTpos; { Current(I) } {[]}
{[]}      {$IFDEF USE_Except }           {[]}
{[]}        _excp: TException;           {[]}
{[]}      {$ENDIF USE_Except }           {[]}
{[]}    END;                             {[]}
{[]}                                     {[]}
{[]}    I_LPR = RECORD                   {[]}
{[]}      Rep : Rep_LPR;                 {[]}
{[]}    END;                             {[]}
{[]}                                     {[]}
{[])=====================================([]}


I.rep.stack es la pila que va a estar como gua, no va a poseer
todos los elementos a regresar como lo haca la cola sino va a
poseer unos cuantos que sirven para ir tomando los otros.  La
pila se est actualizando constantemente.  Siempre el tope de la
pila va a ser el elemento que se manda en el next.

I.rep.T es un puntero al rbol que se va a recorrer.

I.rep.c es el ltimo valor que regreso next osea sirve como
current.

La idea de este iterador es mantener en el tope de la pila el
proximo elemento a mandar segun el orden establecido por medio
del siguiente algorimo:


**  Si el rbol no est vaco mete en la pila todos los
descendientes izquierdos de la raz; empezando desde la raz
misma; osea esta es la primera en ser introducida en la pila (por
las caractersticas de la pila ser la ltima que se saque),
despus se van introduciendo todos sus descendientes izquierdos
por orden de niveles.


**  El next lo que hace es sacar el tope de la pila y pregunta
por su primer hijo:
   
    1.  Si exite pregunta por el hermano derecho del primer hijo  
    osea por el segundo hijo del tope.

        ++  Si tiene segundo hijo introduce el tope a la pila     
        (para recordar quien es el padre), adems introduce al    
        segundo hijo junto con su descendencia izquierda.         

        ++ Sino tiene segundo hijo continue en el punto "2"     

     2.  Sino exite primer o segundo hijo entonces:
         
         Nodo es igual al siguiente en la pila.  Se pregunta si 
        el tope es el primer hijo de nodo:

          Si tope es el primer hijo de nodo quiere decir que que 
          ya se proces todo el subrbol izquierdo y ahora le     
          toca ser procesado al padre;  por lo que se introduce   
          nodo a la pila.

          Sino es el primer hijo, quiere decir que ya se proceso 
          todo el subrbol izquierdo y al padre por lo que tope   
          se iguala al siguiente hermano de tope.

             Si existe quiere decir que se debe procesar el     
             subrbol derecho del subrbol cuya raz es nodo por  
             lo que se inserta nodo a la pila para saber que      
             subrbol se est procesando sin necesidad de invocar 
             a la funcion father de Tree.pas la cual es muy lerda 
             adems se introduce el siguiente hermano osea tope   
             junto con su descendencia izquierda.

             Sino existe quiere decir que ya se proces         
             completo el subrbol, tanto su parte izquierda, como 
             su padre y su parte derecha por lo que tope se       
             iguala a nodo (como para ir subiendo por el rbol) y 
             se repite el proceso desde el punto "2" hasta que la 
             pila este vaca.



Vemos un ejemplo simple para poder entender de la mejor manera:


               [a]
              /  \
             /    \  
            [b]   [c]
            / \    /
          [d] [e] [f]



Como el rbol no est vaco, siguiendo el algoritmo, la pila
queda llena con la descendencia izquierda de la raz:


Ŀ  
@a  
@b
@d < Top
    
El next lo que hace es sacar el tope por lo que el primer next lo
que saca es @d.  Despus de sacarlo se pregunta por su primer
hijo como este no exite se saca el siguiente de la pila que sera
@b y se pregunta si exite entre ellos la relacin de padre y
primer hijo.  Como si existe entonces se introduce  el padre a la
pila osea se introduce de nuevo @b quedando la pila de la
siguiente forma:

Ŀ  
@a  
@b < Top     


El next lo que hace es sacar el tope por lo que el segundo next
lo que saca es @b y pregunta por su primer hijo como este exite,
pregunta por su segundo hijo y como tambin existe introduce el
tope a la pila junto con su segundo hijo.

Ŀ  
@a  
@b
@e < Top

El tercer next lo que va a producir es @e.  Despus pregunta por
su primer hijo, como no tiene toma el siguiente de la pila @b y
pregunta si existe entre ellos la relacin de padre y primer hijo
,como no existe se iguala tope al hermano siguiente de tope ( al
hermano de @e);  pero como tampoco existe entonces tope va a ser
igual a @b y se repiten de nuevo las preguntas.

Tomamos el siguiente de la pila osea @a y preguntamos si entre el
nuevo tope y @a existe la relacin de padre y primer hijo;  como
si existe entonces se introduce @a a la pila:

Ŀ  
@a <  Top

El cuarto next sacar @a.  Despus pregunta por su primer hijo
como este existe (@b), pregunta por su segundo hijo (@c) y como
este tambien existe introduce a la pila al tope, su segundo hijo
y su descendencia izquierda por lo que la pila queda de la
siguiente forma:

Ŀ  
@a  
@c
@f < Top

El quinto next toma a @f.  Pregunta si @f posee primer hijo como
no tiene toma al siguiente de la pila @c y pregunta si entre
ellos existe la relacin padre y primer hijo como si existe dicha
relacion se introduce al padre a la pila @c.


Ŀ  
@a  
@c < Top     

El sexto next toma @c.  Pregunta por su primer hijo como este
exite @f pregunta por el segundo hijo pero como este es nulo
entonces toma al siguiente de la pila que es @a y pregunta si
existe entre ellos la reacion de padre y primer hijo pero como no
existe entonces tope va a ser igual al siguiente hermano de @c . 
Como este no existe entonces tope es igual a @a y se repite el
proceso pero como la pila ya qued vaca se termin el recorrido.


Si hacemos una pequea recopilacin de los seis next que mand el
iterador nos damos cuenta que efectivamente se hizo el recorrido
correcto:

[d b e a f c ]


Bibliografa
============

[1] S_LRP

[2] S_LPR

[3] S_PLR

[4] Q_BF

[5] Q_LRP

[6] Q_LPR

[7] Q_PLR


[8] Liskov, Barbara; Gutag,  John; "Abstraction  and
Specification in Program Development"; McGraw-Hill; 1986.

[9] Di Mare, Adolfo:  "Convenciones de  Programacin para 
Pascal, Revisin 2"; Reporte tcnico ECCI-01-88, ECCI-UCR, 1988.

