]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - doc/informe_2da_entrega.lyx
65f4e092d6b277dc9f3ded925cfdea749ca075b6
[z.facultad/75.06/emufs.git] / doc / informe_2da_entrega.lyx
1 #LyX 1.3 created this file. For more info see http://www.lyx.org/
2 \lyxformat 221
3 \textclass book
4 \language spanish
5 \inputencoding auto
6 \fontscheme palatino
7 \graphics default
8 \paperfontsize default
9 \spacing single 
10 \papersize a4paper
11 \paperpackage widemarginsa4
12 \use_geometry 0
13 \use_amsmath 0
14 \use_natbib 0
15 \use_numerical_citations 0
16 \paperorientation portrait
17 \secnumdepth 3
18 \tocdepth 3
19 \paragraph_separation indent
20 \defskip medskip
21 \quotes_language english
22 \quotes_times 2
23 \papercolumns 1
24 \papersides 1
25 \paperpagestyle default
26
27 \layout Title
28
29 Organización de Datos (75.06)
30 \newline 
31 Trabajo Práctico
32 \newline 
33 E
34 \begin_inset Formula $\mu$
35 \end_inset 
36
37 FS
38 \layout Author
39
40
41 \series bold 
42 Grupo 11
43 \series default 
44
45 \newline 
46 Nicolás Dimov (77624)
47 \newline 
48 Alan Kennedy (78907)
49 \newline 
50 Leandro Lucarella (77891)
51 \newline 
52 Ricardo Markiewicz (78226)
53 \layout Date
54
55 Segunda Entrega, 31 de Mayo de 2004
56 \layout Standard
57
58
59 \begin_inset LatexCommand \tableofcontents{}
60
61 \end_inset 
62
63
64 \layout Chapter
65
66 Introducción
67 \layout Standard
68
69 En esta entrega el trabajo estuvo concentrado en el manejo de índices para
70  los tipos de archivos implementados en la primer entrega.
71  Los índices se implementaron con:
72 \layout Enumerate
73
74 Árbol B
75 \layout Enumerate
76
77 Árbol B*
78 \layout Enumerate
79
80 Árbol B+
81 \layout Standard
82
83 Además de esto, se pide 3 funciones distintas para estos índices:
84 \layout Enumerate
85
86 Principal
87 \layout Enumerate
88
89 Selectivo
90 \layout Enumerate
91
92 Exhaustivo
93 \layout Standard
94
95 Con la autorización de los ayudantes de la cátedra decidimos que el árbol
96  B+ sólo pueda ser utilizado para índices principal ya que de otra manera
97  no tiene sentido el set secuencial.
98 \layout Standard
99
100 Finalmente, para obtener listados basados en campos de los cuales no se
101  tiene un índice, se implementó un ordenamiento externo.
102 \layout Standard
103
104 A continuación se presenta una descripción un poco más detallada sobre todas
105  herramientas utilizadas para resolver el trabajo práctico.
106 \layout Section
107
108 Documentación de la API
109 \layout Standard
110
111 Para obtener una documentación de la API más completa, se incluye en formato
112  HTML en el CD-ROM la documentación generado con Doxygen.
113  Esta documentación se encuentra en el directorio 
114 \family typewriter 
115 doc/api/html/index.html
116 \family default 
117 .
118 \layout Chapter
119
120 Estructura común
121 \layout Section
122
123 Tipos
124 \layout Standard
125
126 Se detallan a continuación los tipos de datos definidos y utilizados en
127  las distintas implementaciones que conforman nuestro sistema, siendo el
128  más importante de ellos en esta entrega, la estructura 
129 \family typewriter 
130 INDICE
131 \family default 
132  que actúa como interfaz común para el manejo de cualquier tipo de índice
133  (no importa que tipo de organización física ni de que forma esté implementado,
134  esta estructura proveerá una interfaz abstracta para su manejo).
135 \layout Subsection
136
137 Tipos Comunes
138 \layout Standard
139
140 Se agregaron varios tipos comunes nuevos en esta entrega, en su mayoría
141  relacionados a los índices.
142  Estos tipos son brevemente descriptos a continuación y pueden ser hallados
143  en el archivo 
144 \family typewriter 
145 indices.h
146 \family default 
147 :
148 \layout Itemize
149
150
151 \family typewriter 
152 INDICE_DATO
153 \family default 
154 : usado para representar el conjunto de un ID más su dato.
155 \layout Itemize
156
157
158 \family typewriter 
159 INDICE_TIPO
160 \family default 
161 : indica el tipo de índice (B, B* o B+).
162 \layout Itemize
163
164
165 \family typewriter 
166 INDICE_FUNCION
167 \family default 
168 : indica la función que cumple el índice (principal, selectivo o exhaustivo).
169 \layout Itemize
170
171
172 \family typewriter 
173 INDICE_TIPO_DATO
174 \family default 
175 : indica el tipo de dato que se usa como clave.
176 \layout Itemize
177
178
179 \family typewriter 
180 CLAVE
181 \family default 
182 : representa una clave de un índice.
183 \layout Subsection
184
185 INDICE
186 \layout Standard
187
188
189 \family typewriter 
190 INDICE
191 \family default 
192 \emph on 
193  
194 \emph default 
195 es la estructura principal que encapsula todas las funciones para el manejo
196  de un índice.
197  Posee punteros a funciones que permite utilizar la misma interfaz para
198  distintas implementaciones de árboles.
199  
200 \layout Standard
201
202 Su declaración puede ser observada en el archivo 
203 \family typewriter 
204 indices.h
205 \family default 
206 \series bold 
207  
208 \series default 
209 y cuenta con la siguiente información:
210 \layout Itemize
211
212 Tipo de índice.
213 \layout Itemize
214
215 Tipo de dato que maneja.
216 \layout Itemize
217
218 Función del índice.
219 \layout Itemize
220
221 Información sobre el desplazamiento para ubicar el dato dentro de la estructura
222  a indexar (para poder tener una implementación genérica que sirva para
223  cualquier estructura).
224 \layout Itemize
225
226 Información sobre archivos auxiliares para almacenar cadenas de texto y
227  otras estructuras que eventualmente requiera un índice.
228 \layout Itemize
229
230 Punteros a funciones para:
231 \begin_deeper 
232 \layout Itemize
233
234 Agregar entrada.
235 \layout Itemize
236
237 Borrar entrada.
238 \layout Itemize
239
240 Verificar la existencia de una entrada.
241 \layout Itemize
242
243 Buscar entradas.
244 \layout Itemize
245
246 Obtener clave menor o mayor del índice.
247 \layout Itemize
248
249 Obtener siguiente clave (para recorrido secuencial).
250 \end_deeper 
251 \layout Standard
252
253 Esta estructura define los valores de sus punteros según el tipo de implementaci
254 ón que se desee manejar y esto se realiza a través de la API 
255 \family typewriter 
256 emufs_indice
257 \family default 
258 , implementada en 
259 \family typewriter 
260 indices.h
261 \family default 
262 .
263  Esta API posee funciones para crear y destruir índices, agregarlos y quitarlos
264  de una estructura 
265 \family typewriter 
266 EMUFS
267 \family default 
268 , comparar claves y otras, necesarias para la correcta y completa utilización
269  de los índices a través de la interfaz de 
270 \family typewriter 
271 EMUFS
272 \family default 
273  descripta en la entrega anterior.
274 \layout Subsubsection
275
276 Integración con 
277 \family typewriter 
278 EMUFS
279 \family default 
280 .
281 \layout Standard
282
283 Para integrar la utilización de índices a 
284 \family typewriter 
285 EMUFS
286 \family default 
287  fueron necesarios los siguientes cambios:
288 \layout Paragraph
289
290 Nuevos tipos de archivo.
291 \layout Standard
292
293 Se incluyen dos tipos de archivo nuevos T4 y T5, que representan, respectivament
294 e, un archivo T1 (registros variables, bloques fijos) y un archivo T3 (registros
295  y bloques fijos), ambos organizados como un set secuencial indexado.
296  De esta manera se conserva la interfaz de 
297 \family typewriter 
298 EMUFS
299 \family default 
300  (los punteros a funciones) incluso cuando se debe insertar de forma ordenada,
301  ya que al saber que es T4 o T5 siempre se inserta de forma ordenada.
302 \layout Paragraph
303
304 Puntero a un arreglo de índices.
305 \layout Standard
306
307 Se agrega a la estructura 
308 \family typewriter 
309 EMUFS
310 \family default 
311  un puntero a un arreglo de 
312 \family typewriter 
313 INDICE
314 \family default 
315 , donde el primero es siempre el índice principal.
316 \layout Chapter
317
318 Especificaciones de índices
319 \layout Section
320
321 Indice B
322 \layout Section
323
324 Indice B*
325 \layout Subsection
326
327 Decisiones de diseño
328 \layout Standard
329
330 Una de las pocas decisiones que tuvimos que tomar fue la forma de manejar
331  el nodo raíz.
332  Hay dos formas comunes de hacerlo:
333 \layout Enumerate
334
335 Permitir que el nodo raíz pueda almacenar 2N+1 claves (siendo N el número
336  máximo de claves permitido por nodo).
337 \layout Enumerate
338
339 Hacer que se comporte como un árbol B.
340 \layout Standard
341
342 La primera forma garantiza un mejor aprovechamiento del espacio, ya que
343  se sigue haciendo una partición en 3 nodos hijo con 2/3 de los espacios
344  llenos.
345  El problema que encontramos para hacerlo de esa forma fue que usamos un
346  tamaño de nodo fijo de 512 para poder leer un sector completo del disco
347  y ganar algo de velocidad, por lo que para poder mantener este esquema
348  hubiéramos necesitado de 3 bloques de 512 para poder guardar los 2N+1 claves,
349  desperdiciando 512-tamaño_de_clave espacio en el bloque final y haciendo
350  que cualquier ahorro de espacio en los hijos del nodo raíz difícilmente
351  lo compense.
352 \layout Standard
353
354 Además de esto, el utilizar la segunda forma trae como ventaja la reutilización
355  de código del árbol B, lo que facilita la implementación y el mantenimiento
356  del código.
357 \layout Standard
358
359 Estas son las dos razones principales por las cuales elegimos tratar el
360  nodo raíz como lo hace el árbol B.
361 \layout Section
362
363 Indice B+ Organizacion Secuencial Indexada
364 \layout Subsection
365
366 Decisiones de diseño
367 \layout Standard
368
369 Para la implementación de la organización secuencial indexada de archivos,
370  se ha utilizado un árbol B+, conocido por ser utilizado en términos generales
371  para implementaciones de esta índole.
372 \layout Standard
373
374 Como particularidad el arbol B+, poseerá en sus hojas todas las claves que
375  se hayan insertado en el árbol.
376  No obstante, las mismas no serán todas las claves que se encuentren en
377  el archivo de datos, sino la primer clave de cada bloque de datos, también
378  denominadas 'anclas de bloque'.
379 \layout Standard
380
381 En torno a esta distinción respecto de los demás arboles, el árbol B+ nos
382  indicará a la hora de grabar registros en nuestro archivo de datos con
383  bloques (Organización del TP1, Tipo1 o 3), en que bloque de datos debemos
384  realizar la mencionada inserción.
385  La operativa se detalla mas adelante, pero basicamente realizaremos una
386  búsqueda del ancla menor inmediata a la clave del registro que se desea
387  insertar, y esto nos indicara el bloque apropiado.
388  (el bloque donde esta el ancla).
389 \layout Standard
390
391 Como resultado concreto de este comportamiento (teniendo en cuenta también
392  el borrado y partición de bloques del .dat), obtendremos un archivo secuencial
393  indexado, en donde los registros se encuentran ordenados a nivel de bloques,
394  esto es, dentro de un bloque dado del archivo de datos, los registros estan
395  ordenados por clave primaria.
396  No obstante, los bloques no estarán necesariamente ordenados, pero igualmente
397  la cantidad de accesos para recorrer el archivo en forma secuencial, se
398  ve minimizada respecto de otras organizaciones, gracias al encadenamiento
399  de las hojas y la posesión de las anclas de bloque, cuya lista resultante
400  del encadenamiento es denominada 
401 \series bold 
402 Sequence Set.
403 \layout Subsection
404
405 Estructura
406 \layout Standard
407
408 Para comprender mejor la implementación particular que hemos dado al árbol
409  B+, damos una breve reseña de la estructura de un nodo del arbol, la cual
410  es la siguiente:
411 \layout Itemize
412
413 Nivel
414 \layout Itemize
415
416 Cantidad de claves
417 \layout Itemize
418
419 Arreglo de claves
420 \layout Itemize
421
422 Arreglo de hijos
423 \layout Standard
424
425 Esta estructura se encuentra en el archivo 
426 \family typewriter 
427 indice_bplus.h
428 \layout Standard
429
430 Esta organización permite, con la ayuda del árbol, mantener el archivo de
431  datos ordenado por la clave principal.
432 \layout Standard
433
434 Para lograr esto, como fue expuesto anteriormente, el árbol nos indicará
435  donde (en qué bloque) debe insertarse un registro.
436  (ver 3.3.1 Inserción)
437 \layout Standard
438
439 En el caso de una hoja, dado que cada nodo posee un hijo mas que la cantidad
440  de claves, el hijo que sobra será utilizado como referencia al nodo 
441 \begin_inset Quotes eld
442 \end_inset 
443
444 hermano
445 \begin_inset Quotes erd
446 \end_inset 
447
448 , lo cual constituye el 
449 \begin_inset Quotes eld
450 \end_inset 
451
452 set secuencial
453 \begin_inset Quotes erd
454 \end_inset 
455
456  del índice.
457  Para un nodo que no sea hoja el hijo será el número de nodo correspondiente
458  según la clave, es decir, para la clave 
459 \series bold 
460 \emph on 
461
462 \series default 
463 \emph default 
464 el hijo 
465 \series bold 
466 \emph on 
467 n
468 \series default 
469 \emph default 
470  contiene claves menores y el hijo 
471 \series bold 
472 \emph on 
473 n+1
474 \series default 
475 \emph default 
476  contiene las claves mayores.
477  En el caso particular del nivel 1 (index set) el hijo 
478 \series bold 
479 \emph on 
480 n+1
481 \series default 
482 \emph default 
483  (sequence set) contiene las claves mayores o iguales ya que el 
484 \begin_inset Quotes eld
485 \end_inset 
486
487 secuence set
488 \begin_inset Quotes erd
489 \end_inset 
490
491  debe contener todas las claves insertadas, esto produce que exista una
492  repetición de las claves entre el nivel 1 y el 0.
493 \layout Standard
494
495 En nuestro caso hemos implementado un Secuencial Indexado tipo ISAM (Indexed
496  Sequential Access Method) el cual posee en sus hojas las anclas de cada
497  bloque en el archivo de datos, es decir, solo se guardan en los nodos del
498  árbol la menor de las claves de un bloque del archivo de datos, acompañada
499  cada clave por el numero de bloque al cual pertenece.
500 \layout Standard
501
502 Hemos adoptado que la cantidad de claves máxima en un nodo del árbol sea
503  una cantidad impar, ya que esto facilita la elección de la clave que será
504  promovida hacia su nodo padre en caso de que se produzca un overflow en
505  el nodo.
506 \layout Subsection
507
508 Inserción
509 \layout Standard
510
511 Para realizar una inserción en el archivo de datos se debe realizar una
512  consulta en el árbol, la cual nos indicará el número de bloque donde debemos
513  insertar el nuevo registro.
514 \layout Standard
515
516 Las consultas se realizan a través de una estructura INDEX_DAT que posee:
517 \layout Itemize
518
519 Clave
520 \layout Itemize
521
522 Número de Bloque 
523 \layout Standard
524
525 Esta estructura se encuentra en el archivo 
526 \family typewriter 
527 indice_bplus.h
528 \layout Standard
529
530 El modo de uso es el siguiente:
531 \layout Standard
532
533 En primer lugar se carga la clave a insertar en el campo Clave, y en el
534  campo Número de Bloque se almacena un número de bloque válido, mas adelante
535  se explica el por qué.
536 \layout Standard
537
538 Luego se invoca a la función 
539 \family typewriter 
540 int emufs_b_plus_get_bloque(INDICE, INDEX_DAT) 
541 \family default 
542 la cual recibe como parámetro una estructura de índice y un INDEX_DAT para
543  realizar la consulta.
544 \layout Standard
545
546 Esta función recorre recursivamente el árbol y busca una clave mayor inmediata
547  a la enviada, siempre culminando la búsqueda en una hoja.
548  Al encontrar la clave mayor inmediata, el resultado de la búsqueda será
549  la clave anterior en el nodo, pues cada clave en el nodo es un ancla de
550  bloque de datos, de esta manera la clave anterior será menor a la clave
551  enviada, pues las claves en las hojas están ordenadas.
552  
553 \layout Standard
554
555 En este paso pueden suceder dos cosas:
556 \layout Enumerate
557
558 Que exista una clave menor a la enviada.
559 \layout Enumerate
560
561 Que la clave enviada sea menor a todas las claves del árbol.
562 \layout Standard
563
564 En el primer caso, se ha encontrado la clave y se carga la estructura con
565  el hijo de esa clave, que será el número de bloque donde debe insertarse
566  el nuevo registro (por el cual se realizó la consulta), sobreescribiendo
567  el valor que almacenaba al ingresar, y la función retornará código 0 que
568  indica que se ha encontrado un bloque donde insertar.
569 \layout Standard
570
571 En el segundo caso, puede darse que la clave enviada sea menor a todas las
572  claves del árbol, por lo cual no es posible encontrar un ancla de bloque
573  para esa clave.
574  Aquí la función retornará código -1 lo cual indica que no se ha encontrado
575  un bloque donde insertar el registro nuevo, y es por esto que la estructura
576  debe inicializarse con un número de bloque válido antes de realizarse la
577  consulta.De esta manera el árbol indica donde debe insertarse un nuevo registro
578  en el archivo de datos.
579 \layout Standard
580
581 Otro detalle de la inserción es que cuando el árbol indica donde debe insertarse
582  un registro pueden pasar dos cosas nuevamente:
583 \layout Enumerate
584
585 Que el registro quepa en el bloque.
586 \layout Enumerate
587
588 Que el registro no quepa en el bloque.
589 \layout Standard
590
591 El primer caso es trivial y el registro se insertará sin problemas en el
592  bloque indicado.
593 \layout Standard
594
595 En el caso que el registro no quepa en el bloque, se deberán separar los
596  registros del bloque en 2 bloques, en original y uno nuevo, cada uno con
597  la mitad (aproximadamente) de los registros.
598  
599 \layout Standard
600
601 Al partir el bloque el ancla del bloque original no se modificará, pero
602  en el bloque nuevo se crea una nueva anlca de bloque, pues una de las claves
603  pertenecientes a los registros que contiene, será la menor.
604 \layout Standard
605
606 Antes de actualizar el árbol con el ancla nueva, habrá que discriminar en
607  qué bloque se debe insertar el registro nuevo.
608  Para ello se compara la menor de las claves del nuevo bloque con la clave
609  del registro, si la clave del registro es menor que el ancla del nuevo
610  bloque, este debe ir en el bloque original, y se inserta ordenado en él
611  y se le informa al árbol que actualice (inserte) una nueva clave correspondient
612 e al bloque nuevo, sino se inserta en el bloque nuevo de forma ordenada
613  y en este caso cabe la posibilidad de que el nuevo registro posea la clave
614  mas pequeña de todas en el bloque, por ello se lo inserta ordenadamente
615  con ayuda de la función
616 \family typewriter 
617  CLAVE grabar_ordenado_en_bloque(EMUFS *emu, void *ptr, EMUFS_REG_SIZE size,
618  void *bloque, int num_bloque, EMUFS_FREE fs, int *err) 
619 \family default 
620 la cual inserta el registro ordenado por CLAVE y devuelve la menor de las
621  claves del bloque, que se usará para informarle al árbol que inserte una
622  clave nueva junto con el número de bloque, para indexar este bloque.
623 \layout Subsection
624
625 Eliminación
626 \layout Standard
627
628 El proceso de eliminación es bastante similar al de inserción en el sentido
629  que también hay que realizar una consulta en el árbol para obtener el número
630  de bloque al que pertenece una clave.
631  Una vez conocido este número se levanta el bloque correspondiente y se
632  busca secuencialmente el registro que se debe eliminar.
633 \layout Standard
634
635 Si el registro a eliminar fuera el primero del bloque, habrá que modificar
636  el ancla de bloque en el árbol con el ancla que corresponda a la clave
637  del nuevo menor registro, y si el que se elimina fuera el único registro
638  en el bloque habrá que eliminar la clave del árbol.
639 \layout Standard
640
641 En cualquier otro caso, solo se eliminará el registro correspondiente y
642  se justificarán los registros a izquierda.
643 \layout Subsection
644
645 Búsqueda
646 \layout Standard
647
648 El proceso de búsqueda de un registro por su clave de identificación primaria
649  en la Organización Secuencial Indexada, es bastante directa en su entendimiento.
650  Para buscar un registro, acudiremos al árbol B+ con la clave anteriormente
651  mencionada, y obtendremos del mismo, el numero de bloque donde se debe
652  encontrar el registro.
653 \layout Standard
654
655 Para obtener dicho número de bloque, el árbol internamente busca el ancla
656  menor inmediata a la clave buscada y luego devuelve el número de bloque
657  de datos donde está dicha ancla (el nro bloque será el dato asociado a
658  la clave ancla, en el árbol), el cual será el bloque potencial donde se
659  encuentre el registro buscado.
660 \layout Standard
661
662 Una desventaja de esta implementación con indexación parcial, es que no
663  sabremos si el registro se encuentra efectivamente en el bloque indicado,
664  hasta no buscarlo dentro del mismo en formal secuencial.
665  Si lo hallamos, daremos por finalizada la búsqueda del registro.
666 \layout Subsection
667
668 Recorrida secuencial de registros
669 \layout Standard
670
671 Una consecuencia importante de la organización secuencial indexada, en este
672  caso implementada a través de un árbol B+ con indexación parcial, es que
673  como mencionamos anteriormente, los registros dentro de un bloque se encuetran
674  ordenados, y si bien los bloques en si pueden estar no ordenados en el
675  archivo de datos, algunos lo estaran, y minimizarán en base a estas cosa
676  características, los tiempos de acceso para una recorrida secuencial de
677  registros.
678 \layout Standard
679
680 Suponiendo que nos encontramos con varios registros cargados en esta organizació
681 n de archivo, y con el correspondiente árbol de indexación primaria B+ en
682  el disco, si se nos pidiera por ejemplo, recorrer los registros de articulos
683  desde el ID_Articulo 40, hasta el ID_Articulo 1406, la operativa será la
684  siguiente:
685 \layout Itemize
686
687 Acudimos al árbol y obtenemos el numero de bloque para el ID_Articulo 40,
688  buscando el ancla menor inmediata y obteniendo el nro de bloque de datos
689  donde se encuentra, siendo este el nro de bloque donde debería estar el
690  artículo de clave ID_Articulo 40.
691 \layout Itemize
692
693 Levantamos el bloque de datos y lo recorremos secuencialmente, pues como
694  dijimos anteriormente, sus registros se encuentran ordenados por la clave
695  de identificación primaria, en este caso ID_Articulo.
696 \layout Itemize
697
698 Cuando ya hallamos procesado todo el bloque, debemos obtener la siguiente
699  ancla a través del árbol y repetir el proceso.
700 \layout Itemize
701
702 NOTA: Cabe desatacar, que todas las anclas estan en las hojas del B+, y
703  por ello las recorremos a nivel hojas a traves del Sequence Set, que gracias
704  a su encadenamiento, nos permite obtener en forma muy directa y efectiva,
705  las anclas de bloque ordenadas en secuencia, y por consiguiente, recorrer
706  el archivo en forma secuencial minimizando accesos.
707 \layout Chapter
708
709 Ordenamiento Externo
710 \layout Section
711
712 Descripción del algoritmo
713 \layout Standard
714
715 Luego de buscar varias alternativas sobre algoritmos de ordenamiento externo,
716  se optó por el siguiente (que resultó una mezcla de las alternativas analizadas
717 ):
718 \layout Enumerate
719
720 Tomar uno a uno los registros del archivo a ordenar e 
721 \emph on 
722 inyectarlos
723 \emph default 
724  en un buffer ordenado hasta llenar el buffer.
725 \layout Enumerate
726
727 Quitar el menor de los valores (
728 \emph on 
729 inyectando
730 \emph default 
731  uno nuevo desde el archivo a ordenar) e insertarlo en un archivo temporal.
732 \layout Enumerate
733
734 Quitar del buffer el mínimo valor mayor al último insertado en el archivo
735  temporal (
736 \emph on 
737 inyectando
738 \emph default 
739  nuevamente un registro obtenido del archivo a ordenar) y se lo inserta
740  en el archivo temporal.
741  De esta forma quedan ordenados los registros en el archivo temporal.
742 \layout Enumerate
743
744 Repetir el paso 3 hasta que se vacíe el buffer o hasta que no haya ningún
745  valor mayor al último insertado en el archivo temporal.
746  Cuando esto suceda se crea un nuevo archivo temporal volviendo al paso
747  2.
748 \layout Standard
749
750 En este punto ya tenemos el buffer vacío y todos los valores del archivo
751  a ordenar repartidos en 1 o más archivos temporales ordenados, sólo queda
752  unir los archivos para volver a un sólo archivo completo y ordenado.
753  El procedimiento es simple:
754 \layout Enumerate
755
756 Obtener el mínimo valor de los archivos temporales e insertarlo en el archivo
757  ordenado de salida.
758 \layout Enumerate
759
760 Repetir 1 hasta agotar los registros de todos los archivos temporales.
761 \layout Standard
762
763 Debe quedar claro que los archivos temporales se comportan como una cola.
764  Es decir que al obtener un registro de un archivo temporal se obtiene el
765  primer registro que se haya insertado (el mínimo por la forma en la que
766  fueron insertados).
767 \layout Subsection
768
769 Ejemplo
770 \layout Standard
771
772 A continuación se presenta un ejemplo para una más fácil comprensión del
773  algoritmo.
774 \layout Standard
775
776 Supongamos que queremos ordenar un archivo con registros de números enteros
777  (el archivo se lee de izquierda a derecha): 9 6 34 2 8 3 12 43 23 4 19
778  21 87 1 16 36 42 65
779 \layout Standard
780
781 Supongamos que disponemos de un buffer capaz de almacenar 3 registros.
782 \layout Paragraph
783
784 Se llena el buffer ordenado
785 \layout Standard
786
787 Se lee 9 del archivo original y se lo inserta en el buffer ordenado.
788  Buffer: 9
789 \layout Standard
790
791 Se lee 6 del archivo original y se lo inserta en el buffer ordenado.
792  Buffer: 6 9
793 \layout Standard
794
795 Se lee 34 del archivo original y se lo inserta en el buffer ordenado.
796  Buffer: 6 9 34
797 \layout Paragraph
798
799 Se crea el archivo temporal ordenado 1
800 \layout Standard
801
802 Se lee el mínimo valor del buffer (6), se lo inserta en el archivo temporal
803  y se carga un nuevo valor del archivo original al buffer (2).
804  Buffer: 2 9 34.
805  Archivo1: 6
806 \layout Standard
807
808 Se lee el mínimo valor del buffer mayor al insertado anteriormente (9),
809  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
810  original al buffer (8).
811  Buffer: 2 8 34.
812  Archivo1: 6 9
813 \layout Standard
814
815 Se lee el mínimo valor del buffer mayor al insertado anteriormente (34),
816  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
817  original al buffer (3).
818  Buffer: 2 3 8.
819  Archivo1: 6 9 34
820 \layout Standard
821
822 No hay más valores en el buffer mayores al último insertado (34), fin del
823  Archivo1.
824 \layout Paragraph
825
826 Se crea el archivo temporal ordenado 2
827 \layout Standard
828
829 Se lee el mínimo valor del buffer (2), se lo inserta en el archivo temporal
830  y se carga un nuevo valor del archivo original al buffer (12).
831  Buffer: 3 8 12.
832  Archivo2: 2
833 \layout Standard
834
835 Se lee el mínimo valor del buffer mayor al insertado anteriormente (3),
836  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
837  original al buffer (43).
838  Buffer: 8 12 43.
839  Archivo2: 2 3
840 \layout Standard
841
842 Se lee el mínimo valor del buffer mayor al insertado anteriormente (8),
843  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
844  original al buffer (23).
845  Buffer: 12 23 43.
846  Archivo2: 2 3 8
847 \layout Standard
848
849 Se lee el mínimo valor del buffer mayor al insertado anteriormente (12),
850  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
851  original al buffer (4).
852  Buffer: 4 23 43.
853  Archivo2: 2 3 8 12
854 \layout Standard
855
856 Se lee el mínimo valor del buffer mayor al insertado anteriormente (23),
857  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
858  original al buffer (19).
859  Buffer: 4 19 43.
860  Archivo2: 2 3 8 12 23
861 \layout Standard
862
863 Se lee el mínimo valor del buffer mayor al insertado anteriormente (43),
864  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
865  original al buffer (21).
866  Buffer: 4 19 21.
867  Archivo2: 2 3 8 12 23 43
868 \layout Standard
869
870 No hay más valores en el buffer mayores al último insertado (43), fin del
871  Archivo2.
872 \layout Paragraph
873
874 Se crea el archivo temporal ordenado 3
875 \layout Standard
876
877 Se repite el proceso anterior.
878  Buffer: 1 16 36.
879  Archivo3: 4 19 21 87
880 \layout Paragraph
881
882 Se crea el archivo temporal ordenado 4
883 \layout Standard
884
885 Se repite el proceso anterior.
886  Buffer: .
887  Archivo4: 1 16 36 42 65
888 \layout Paragraph
889
890 Se mezclan los archivos temporales ordenados obteniendo un archivo completo
891  ordenado
892 \layout Standard
893
894 Se obtiene el menor valor de los archivos temporales ordenados (sólo tenemos
895  que elegir entre el primer valor de cada uno).
896 \layout Standard
897
898 Archivo1: 6 9 34.
899  Archivo2: 2 3 8 12 23 43.
900  Archivo3: 4 19 21 87.
901  Archivo4: 1 16 36 42 65
902 \layout Standard
903
904 Sólo debo comparar y obtener el menor entre 6, 2, 4, y 1.
905  Obtengo el 1, lo saco del archivo temporal y lo agrego al de salida:
906 \layout Standard
907
908 Archivo1: 6 9 34.
909  Archivo2: 2 3 8 12 23 43.
910  Archivo3: 4 19 21 87.
911  Archivo4: 16 36 42 65 Salida: 1
912 \layout Standard
913
914 Repito hasta que no hayan más valores en los archivos temporales:
915 \layout Standard
916
917 Archivo1: 6 9 34.
918  Archivo2: 3 8 12 23 43.
919  Archivo3: 4 19 21 87.
920  Archivo4: 16 36 42 65.
921  Salida: 1 2
922 \layout Standard
923
924 Archivo1: 6 9 34.
925  Archivo2: 8 12 23 43.
926  Archivo3: 4 19 21 87.
927  Archivo4: 16 36 42 65.
928  Salida: 1 2 3
929 \layout Standard
930
931 Archivo1: 6 9 34.
932  Archivo2: 8 12 23 43.
933  Archivo3: 19 21 87.
934  Archivo4: 16 36 42 65.
935  Salida: 1 2 3 4
936 \layout Standard
937
938 Archivo1: 6 9 34.
939  Archivo2: 8 12 23 43.
940  Archivo3: 19 21 87.
941  Archivo4: 16 36 42 65.
942  Salida: 1 2 3 4
943 \layout Standard
944
945 Archivo1: 9 34.
946  Archivo2: 8 12 23 43.
947  Archivo3: 19 21 87.
948  Archivo4: 16 36 42 65.
949  Salida: 1 2 3 4 6
950 \layout Standard
951
952 Archivo1: 9 34.
953  Archivo2: 12 23 43.
954  Archivo3: 19 21 87.
955  Archivo4: 16 36 42 65.
956  Salida: 1 2 3 4 6 8
957 \layout Standard
958
959 Archivo1: 34.
960  Archivo2: 12 23 43.
961  Archivo3: 19 21 87.
962  Archivo4: 16 36 42 65.
963  Salida: 1 2 3 4 6 8 9
964 \layout Standard
965
966 Archivo1: 34.
967  Archivo2: 23 43.
968  Archivo3: 19 21 87.
969  Archivo4: 16 36 42 65.
970  Salida: 1 2 3 4 6 8 9 12
971 \layout Standard
972
973 Archivo1: 34.
974  Archivo2: 23 43.
975  Archivo3: 19 21 87.
976  Archivo4: 36 42 65.
977  Salida: 1 2 3 4 6 8 9 12 16
978 \layout Standard
979
980 Archivo1: 34.
981  Archivo2: 23 43.
982  Archivo3: 21 87.
983  Archivo4: 36 42 65.
984  Salida: 1 2 3 4 6 8 9 12 16 19
985 \layout Standard
986
987 Archivo1: 34.
988  Archivo2: 23 43.
989  Archivo3: 87.
990  Archivo4: 36 42 65.
991  Salida: 1 2 3 4 6 8 9 12 16 19 21
992 \layout Standard
993
994 Archivo1: 34.
995  Archivo2: 43.
996  Archivo3: 87.
997  Archivo4: 36 42 65.
998  Salida: 1 2 3 4 6 8 9 12 16 19 21 23
999 \layout Standard
1000
1001 Archivo1:.
1002  Archivo2: 43.
1003  Archivo3: 87.
1004  Archivo4: 36 42 65.
1005  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34
1006 \layout Standard
1007
1008 Archivo1:.
1009  Archivo2: 43.
1010  Archivo3: 87.
1011  Archivo4: 42 65.
1012  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36
1013 \layout Standard
1014
1015 Archivo1:.
1016  Archivo2: 43.
1017  Archivo3: 87.
1018  Archivo4: 65.
1019  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42
1020 \layout Standard
1021
1022 Archivo1:.
1023  Archivo2:.
1024  Archivo3: 87.
1025  Archivo4: 65.
1026  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42 43
1027 \layout Standard
1028
1029 Archivo1:.
1030  Archivo2:.
1031  Archivo3: 87.
1032  Archivo4:.
1033  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42 43 65
1034 \layout Standard
1035
1036 Archivo1:.
1037  Archivo2:.
1038  Archivo3:.
1039  Archivo4:.
1040  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42 43 65 87
1041 \layout Paragraph
1042
1043 Fin
1044 \layout Standard
1045
1046 Finalmente, tengo en el archivo de salida el archivo original ordenado.
1047 \layout Section
1048
1049 Alcance
1050 \layout Standard
1051
1052 El algoritmo de ordenamiento es completamente genérico, ya que recibe un
1053  puntero void como registro, su tamaño (para poder manipularlo sin conocer
1054  su tipo) y una función de comparación, para poder comparar dos registros
1055  (sin saber su tipo) a través de una relación de orden (descripta por dicha
1056  función).
1057 \layout Section
1058
1059 Decisiones de diseño.
1060 \layout Standard
1061
1062 El algoritmo se eligió en base a una serie de razones y cuenta con una serie
1063  de ventajas y desventajas.
1064 \layout Itemize
1065
1066 El algoritmo es simple, tanto teóricamente como para implementar.
1067 \layout Itemize
1068
1069 Tiene la desventaja de que puede llegar a usar muchos archivos temporales
1070  y todos abiertos al mismo tiempo, pero considerando que el sistema operativo
1071  en el que se utiliza suele manejar bien grandes cantidades de archivos
1072  no es una desventaja importante.
1073 \layout Itemize
1074
1075 Al usar un buffer intermedio, se puede controlar muy bien la cantidad de
1076  memoria que utiliza y experimentar con distintos valores para analizar
1077  los resultados.
1078 \layout Itemize
1079
1080 El buffer ordenado se implementó con un árbol binario debido a que tiene
1081  una buena relación entre velocidad de búsqueda y facilidad de implementación.
1082  Al ser el principal determinante de la velocidad los accesos a disco no
1083  se creyó necesario buscar una alternativa más rápida para mantener el buffer
1084  ordenado en memoria, ya que no cambiaría de forma notable el tiempo total
1085  del algoritmo.
1086  Otras posibilidades hubieran sido cargar todo el buffer en memoria y ordenarlo
1087  posteriormente (dependiendo del algoritmo de ordenamiento a utilizar puede
1088  ser más o menos rápido que el árbol y más o menos complicado de implementar)
1089  o hacer una búsqueda secuencial sobre un buffer desordenado (es más fácil
1090  de implementar pero claramente más lento).
1091  Una posible ventaja notable de leer el buffer primero y luego ordenarlo
1092  en memoria es que se necesita un sólo acceso al disco para llenar el buffer,
1093  mientras que al obtener uno a uno los valores puede generar muchos accesos
1094  a disco.
1095  Esto no debería ser muy notable ya que las funciones de acceso a archivos
1096  de la biblioteca estándar de C poseen un buffer interno, por lo que los
1097  accesos a disco probablemente sea muy poco aún cuando se obtienen uno a
1098  uno.
1099 \the_end