]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - doc/informe_2da_entrega.lyx
comiteo pequeños cambios hasta que se me ocurra algo mas que poner
[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+ Secuencial Indexado
364 \layout Subsection
365
366 Decisiones de diseño
367 \layout Standard
368
369 Se ha implementado un índice secuencial indexado utilizando un árbol B+,
370  el cual tiene la particularidad de tener en sus hojas todas las claves
371  que se han insertado.
372 \layout Standard
373
374 La estructura de un nodo del árbol es la siguiente:
375 \layout Itemize
376
377 Nivel
378 \layout Itemize
379
380 Cantidad de claves
381 \layout Itemize
382
383 Arreglo de claves
384 \layout Itemize
385
386 Arreglo de hijos
387 \layout Standard
388
389 Esta estructura se encuentra en el archivo 
390 \family typewriter 
391 indice_bplus.h
392 \layout Standard
393
394 Esta organización permite, con la ayuda del árbol, mantener el archivo de
395  datos ordenado por la clave principal.
396 \layout Standard
397
398 Para lograr esto, el árbol nos indicará donde (en qué bloque) debe insertarse
399  un registro.
400  (ver 3.3.1 Inserción)
401 \layout Standard
402
403 En el caso de una hoja, dado que cada nodo posee un hijo mas que la cantidad
404  de claves, el hijo que sobra será utilizado como referencia al nodo 
405 \begin_inset Quotes eld
406 \end_inset 
407
408 hermano
409 \begin_inset Quotes erd
410 \end_inset 
411
412 , lo cual constituye el 
413 \begin_inset Quotes eld
414 \end_inset 
415
416 set secuencial
417 \begin_inset Quotes erd
418 \end_inset 
419
420  del índice.
421  Para un nodo que no sea hoja el hijo será el número de nodo correspondiente
422  según la clave, es decir, para la clave 
423 \series bold 
424 \emph on 
425
426 \series default 
427 \emph default 
428 el hijo 
429 \series bold 
430 \emph on 
431 n
432 \series default 
433 \emph default 
434  contiene claves menores y el hijo 
435 \series bold 
436 \emph on 
437 n+1
438 \series default 
439 \emph default 
440  contiene las claves mayores.
441  En el caso particular del nivel 1 (index set) el hijo 
442 \series bold 
443 \emph on 
444 n+1
445 \series default 
446 \emph default 
447  (secuence set) contiene las claves mayores o iguales ya que el 
448 \begin_inset Quotes eld
449 \end_inset 
450
451 secuence set
452 \begin_inset Quotes erd
453 \end_inset 
454
455  debe contener todas las claves insertadas, esto produce que exista una
456  repetición de las claves entre el nivel 1 y el 0.
457 \layout Standard
458
459 En nuestro caso hemos implementado un Secuencial Indexado tipo ISAM (Indexed
460  Sequential Access Method) el cual posee en sus hojas las anclas de cada
461  bloque en el archivo de datos, es decir, solo se guardan en los nodos del
462  árbol la menor de las claves de un bloque del archivo de datos, acompañada
463  cada clave por el numero de bloque al cual pertenece.
464 \layout Standard
465
466 Hemos adoptado que la cantidad de claves máxima en un nodo del árbol sea
467  una cantidad impar, ya que esto facilita la elección de la clave que será
468  promovida hacia su nodo padre en caso de que se produzca un overflow en
469  el nodo.
470 \layout Subsection
471
472 Inserción
473 \layout Standard
474
475 Para realizar una inserción en el archivo de datos se debe realizar una
476  consulta en el árbol, la cual nos indicará el número de bloque donde debemos
477  insertar el nuevo registro.
478 \layout Standard
479
480 Las consultas se realizan a través de una estructura INDEX_DAT que posee:
481 \layout Itemize
482
483 Clave
484 \layout Itemize
485
486 Número de Bloque 
487 \layout Standard
488
489 Esta estructura se encuentra en el archivo 
490 \family typewriter 
491 indice_bplus.h
492 \layout Standard
493
494 El modo de uso es el siguiente:
495 \layout Standard
496
497 En primer lugar se carga la clave a insertar en el campo Clave, y en el
498  campo Número de Bloque se almacena un número de bloque válido, mas adelante
499  se explica el por qué.
500 \layout Standard
501
502 Luego se invoca a la función 
503 \family typewriter 
504 int emufs_b_plus_get_bloque(INDICE, INDEX_DAT) 
505 \family default 
506 la cual recibe como parámetro una estructura de índice y un INDEX_DAT para
507  realizar la consulta.
508 \layout Standard
509
510 Esta función recorre recursivamente el árbol y busca una clave mayor inmediata
511  a la enviada, siempre culminando la búsqueda en una hoja.
512  Al encontrar la clave mayor inmediata, el resultado de la búsqueda será
513  la clave anterior en el nodo, pues cada clave en el nodo es un ancla de
514  bloque de datos, de esta manera la clave anterior será menor a la clave
515  enviada, pues las claves en las hojas están ordenadas.
516  
517 \layout Standard
518
519 En este paso pueden suceder dos cosas:
520 \layout Enumerate
521
522 Que exista una clave menor a la enviada.
523 \layout Enumerate
524
525 Que la clave enviada sea menor a todas las claves del árbol.
526 \layout Standard
527
528 En el primer caso, se ha encontrado la clave y se carga la estructura con
529  el hijo de esa clave, que será el número de bloque donde debe insertarse
530  el nuevo registro (por el cual se realizó la consulta), sobreescribiendo
531  el valor que almacenaba al ingresar, y la función retornará código 0 que
532  indica que se ha encontrado un bloque donde insertar.
533 \layout Standard
534
535 En el segundo caso, puede darse que la clave enviada sea menor a todas las
536  claves del árbol, por lo cual no es posible encontrar un ancla de bloque
537  para esa clave.
538  Aquí la función retornará código -1 lo cual indica que no se ha encontrado
539  un bloque donde insertar el registro nuevo, y es por esto que la estructura
540  debe inicializarse con un número de bloque válido antes de realizarse la
541  consulta.De esta manera el árbol indica donde debe insertarse un nuevo registro
542  en el archivo de datos.
543 \layout Standard
544
545 Otro detalle de la inserción es que cuando el árbol indica donde debe insertarse
546  un registro pueden pasar dos cosas nuevamente:
547 \layout Enumerate
548
549 Que el registro quepa en el bloque.
550 \layout Enumerate
551
552 Que el registro no quepa en el bloque.
553 \layout Standard
554
555 El primer caso es trivial y el registro se insertará sin problemas en el
556  bloque indicado.
557 \layout Standard
558
559 En el caso que el registro no quepa en el bloque, se deberán separar los
560  registros del bloque en 2 bloques, en original y uno nuevo, cada uno con
561  la mitad (aproximadamente) de los registros.
562  
563 \layout Standard
564
565 Al partir el bloque el ancla del bloque original no se modificará, pero
566  en el bloque nuevo se crea una nueva anlca de bloque, pues una de las claves
567  pertenecientes a los registros que contiene, será la menor.
568 \layout Standard
569
570 Antes de actualizar el árbol con el ancla nueva, habrá que discriminar en
571  qué bloque se debe insertar el registro nuevo.
572  Para ello se compara la menor de las claves del nuevo bloque con la clave
573  del registro, si la clave del registro es menor que el ancla del nuevo
574  bloque, este debe ir en el bloque original, y se inserta ordenado en él
575  y se le informa al árbol que actualice (inserte) una nueva clave correspondient
576 e al bloque nuevo, sino se inserta en el bloque nuevo de forma ordenada
577  y en este caso cabe la posibilidad de que el nuevo registro posea la clave
578  mas pequeña de todas en el bloque, por ello se lo inserta ordenadamente
579  con ayuda de la función
580 \family typewriter 
581  CLAVE grabar_ordenado_en_bloque(EMUFS *emu, void *ptr, EMUFS_REG_SIZE size,
582  void *bloque, int num_bloque, EMUFS_FREE fs, int *err) 
583 \family default 
584 la cual inserta el registro ordenado por CLAVE y devuelve la menor de las
585  claves del bloque, que se usará para informarle al árbol que inserte una
586  clave nueva junto con el número de bloque, para indexar este bloque.
587 \layout Subsection
588
589 Eliminación
590 \layout Standard
591
592 El proceso de eliminación es bastante similar al de inserción en el sentido
593  que también hay que realizar una consulta en el árbol para obtener el número
594  de bloque al que pertenece una clave.
595  Una vez conocido este número se levanta el bloque correspondiente y se
596  busca secuencialmente el registro que se debe eliminar.
597 \layout Standard
598
599 Si el registro a eliminar fuera el primero del bloque, habrá que modificar
600  el ancla de bloque en el árbol con el ancla que corresponda a la clave
601  del nuevo menor registro, y si el que se elimina fuera el único registro
602  en el bloque habrá que eliminar la clave del árbol.
603 \layout Standard
604
605 En cualquier otro caso, solo se eliminará el registro correspondiente y
606  se justificarán los regitros a izquierda.
607 \layout Chapter
608
609 Ordenamiento Externo
610 \layout Section
611
612 Descripción del algoritmo
613 \layout Standard
614
615 Luego de buscar varias alternativas sobre algoritmos de ordenamiento externo,
616  se optó por el siguiente (que resultó una mezcla de las alternativas analizadas
617 ):
618 \layout Enumerate
619
620 Tomar uno a uno los registros del archivo a ordenar e 
621 \emph on 
622 inyectarlos
623 \emph default 
624  en un buffer ordenado hasta llenar el buffer.
625 \layout Enumerate
626
627 Quitar el menor de los valores (
628 \emph on 
629 inyectando
630 \emph default 
631  uno nuevo desde el archivo a ordenar) e insertarlo en un archivo temporal.
632 \layout Enumerate
633
634 Quitar del buffer el mínimo valor mayor al último insertado en el archivo
635  temporal (
636 \emph on 
637 inyectando
638 \emph default 
639  nuevamente un registro obtenido del archivo a ordenar) y se lo inserta
640  en el archivo temporal.
641  De esta forma quedan ordenados los registros en el archivo temporal.
642 \layout Enumerate
643
644 Repetir el paso 3 hasta que se vacíe el buffer o hasta que no haya ningún
645  valor mayor al último insertado en el archivo temporal.
646  Cuando esto suceda se crea un nuevo archivo temporal volviendo al paso
647  2.
648 \layout Standard
649
650 En este punto ya tenemos el buffer vacío y todos los valores del archivo
651  a ordenar repartidos en 1 o más archivos temporales ordenados, sólo queda
652  unir los archivos para volver a un sólo archivo completo y ordenado.
653  El procedimiento es simple:
654 \layout Enumerate
655
656 Obtener el mínimo valor de los archivos temporales e insertarlo en el archivo
657  ordenado de salida.
658 \layout Enumerate
659
660 Repetir 1 hasta agotar los registros de todos los archivos temporales.
661 \layout Standard
662
663 Debe quedar claro que los archivos temporales se comportan como una cola.
664  Es decir que al obtener un registro de un archivo temporal se obtiene el
665  primer registro que se haya insertado (el mínimo por la forma en la que
666  fueron insertados).
667 \layout Subsection
668
669 Ejemplo
670 \layout Standard
671
672 A continuación se presenta un ejemplo para una más fácil comprensión del
673  algoritmo.
674 \layout Standard
675
676 Supongamos que queremos ordenar un archivo con registros de números enteros
677  (el archivo se lee de izquierda a derecha): 9 6 34 2 8 3 12 43 23 4 19
678  21 87 1 16 36 42 65
679 \layout Standard
680
681 Supongamos que disponemos de un buffer capaz de almacenar 3 registros.
682 \layout Paragraph
683
684 Se llena el buffer ordenado
685 \layout Standard
686
687 Se lee 9 del archivo original y se lo inserta en el buffer ordenado.
688  Buffer: 9
689 \layout Standard
690
691 Se lee 6 del archivo original y se lo inserta en el buffer ordenado.
692  Buffer: 6 9
693 \layout Standard
694
695 Se lee 34 del archivo original y se lo inserta en el buffer ordenado.
696  Buffer: 6 9 34
697 \layout Paragraph
698
699 Se crea el archivo temporal ordenado 1
700 \layout Standard
701
702 Se lee el mínimo valor del buffer (6), se lo inserta en el archivo temporal
703  y se carga un nuevo valor del archivo original al buffer (2).
704  Buffer: 2 9 34.
705  Archivo1: 6
706 \layout Standard
707
708 Se lee el mínimo valor del buffer mayor al insertado anteriormente (9),
709  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
710  original al buffer (8).
711  Buffer: 2 8 34.
712  Archivo1: 6 9
713 \layout Standard
714
715 Se lee el mínimo valor del buffer mayor al insertado anteriormente (34),
716  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
717  original al buffer (3).
718  Buffer: 2 3 8.
719  Archivo1: 6 9 34
720 \layout Standard
721
722 No hay más valores en el buffer mayores al último insertado (34), fin del
723  Archivo1.
724 \layout Paragraph
725
726 Se crea el archivo temporal ordenado 2
727 \layout Standard
728
729 Se lee el mínimo valor del buffer (2), se lo inserta en el archivo temporal
730  y se carga un nuevo valor del archivo original al buffer (12).
731  Buffer: 3 8 12.
732  Archivo2: 2
733 \layout Standard
734
735 Se lee el mínimo valor del buffer mayor al insertado anteriormente (3),
736  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
737  original al buffer (43).
738  Buffer: 8 12 43.
739  Archivo2: 2 3
740 \layout Standard
741
742 Se lee el mínimo valor del buffer mayor al insertado anteriormente (8),
743  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
744  original al buffer (23).
745  Buffer: 12 23 43.
746  Archivo2: 2 3 8
747 \layout Standard
748
749 Se lee el mínimo valor del buffer mayor al insertado anteriormente (12),
750  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
751  original al buffer (4).
752  Buffer: 4 23 43.
753  Archivo2: 2 3 8 12
754 \layout Standard
755
756 Se lee el mínimo valor del buffer mayor al insertado anteriormente (23),
757  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
758  original al buffer (19).
759  Buffer: 4 19 43.
760  Archivo2: 2 3 8 12 23
761 \layout Standard
762
763 Se lee el mínimo valor del buffer mayor al insertado anteriormente (43),
764  se lo inserta en el archivo temporal y se carga un nuevo valor del archivo
765  original al buffer (21).
766  Buffer: 4 19 21.
767  Archivo2: 2 3 8 12 23 43
768 \layout Standard
769
770 No hay más valores en el buffer mayores al último insertado (43), fin del
771  Archivo2.
772 \layout Paragraph
773
774 Se crea el archivo temporal ordenado 3
775 \layout Standard
776
777 Se repite el proceso anterior.
778  Buffer: 1 16 36.
779  Archivo3: 4 19 21 87
780 \layout Paragraph
781
782 Se crea el archivo temporal ordenado 4
783 \layout Standard
784
785 Se repite el proceso anterior.
786  Buffer: .
787  Archivo4: 1 16 36 42 65
788 \layout Paragraph
789
790 Se mezclan los archivos temporales ordenados obteniendo un archivo completo
791  ordenado
792 \layout Standard
793
794 Se obtiene el menor valor de los archivos temporales ordenados (sólo tenemos
795  que elegir entre el primer valor de cada uno).
796 \layout Standard
797
798 Archivo1: 6 9 34.
799  Archivo2: 2 3 8 12 23 43.
800  Archivo3: 4 19 21 87.
801  Archivo4: 1 16 36 42 65
802 \layout Standard
803
804 Sólo debo comparar y obtener el menor entre 6, 2, 4, y 1.
805  Obtengo el 1, lo saco del archivo temporal y lo agrego al de salida:
806 \layout Standard
807
808 Archivo1: 6 9 34.
809  Archivo2: 2 3 8 12 23 43.
810  Archivo3: 4 19 21 87.
811  Archivo4: 16 36 42 65 Salida: 1
812 \layout Standard
813
814 Repito hasta que no hayan más valores en los archivos temporales:
815 \layout Standard
816
817 Archivo1: 6 9 34.
818  Archivo2: 3 8 12 23 43.
819  Archivo3: 4 19 21 87.
820  Archivo4: 16 36 42 65.
821  Salida: 1 2
822 \layout Standard
823
824 Archivo1: 6 9 34.
825  Archivo2: 8 12 23 43.
826  Archivo3: 4 19 21 87.
827  Archivo4: 16 36 42 65.
828  Salida: 1 2 3
829 \layout Standard
830
831 Archivo1: 6 9 34.
832  Archivo2: 8 12 23 43.
833  Archivo3: 19 21 87.
834  Archivo4: 16 36 42 65.
835  Salida: 1 2 3 4
836 \layout Standard
837
838 Archivo1: 6 9 34.
839  Archivo2: 8 12 23 43.
840  Archivo3: 19 21 87.
841  Archivo4: 16 36 42 65.
842  Salida: 1 2 3 4
843 \layout Standard
844
845 Archivo1: 9 34.
846  Archivo2: 8 12 23 43.
847  Archivo3: 19 21 87.
848  Archivo4: 16 36 42 65.
849  Salida: 1 2 3 4 6
850 \layout Standard
851
852 Archivo1: 9 34.
853  Archivo2: 12 23 43.
854  Archivo3: 19 21 87.
855  Archivo4: 16 36 42 65.
856  Salida: 1 2 3 4 6 8
857 \layout Standard
858
859 Archivo1: 34.
860  Archivo2: 12 23 43.
861  Archivo3: 19 21 87.
862  Archivo4: 16 36 42 65.
863  Salida: 1 2 3 4 6 8 9
864 \layout Standard
865
866 Archivo1: 34.
867  Archivo2: 23 43.
868  Archivo3: 19 21 87.
869  Archivo4: 16 36 42 65.
870  Salida: 1 2 3 4 6 8 9 12
871 \layout Standard
872
873 Archivo1: 34.
874  Archivo2: 23 43.
875  Archivo3: 19 21 87.
876  Archivo4: 36 42 65.
877  Salida: 1 2 3 4 6 8 9 12 16
878 \layout Standard
879
880 Archivo1: 34.
881  Archivo2: 23 43.
882  Archivo3: 21 87.
883  Archivo4: 36 42 65.
884  Salida: 1 2 3 4 6 8 9 12 16 19
885 \layout Standard
886
887 Archivo1: 34.
888  Archivo2: 23 43.
889  Archivo3: 87.
890  Archivo4: 36 42 65.
891  Salida: 1 2 3 4 6 8 9 12 16 19 21
892 \layout Standard
893
894 Archivo1: 34.
895  Archivo2: 43.
896  Archivo3: 87.
897  Archivo4: 36 42 65.
898  Salida: 1 2 3 4 6 8 9 12 16 19 21 23
899 \layout Standard
900
901 Archivo1:.
902  Archivo2: 43.
903  Archivo3: 87.
904  Archivo4: 36 42 65.
905  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34
906 \layout Standard
907
908 Archivo1:.
909  Archivo2: 43.
910  Archivo3: 87.
911  Archivo4: 42 65.
912  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36
913 \layout Standard
914
915 Archivo1:.
916  Archivo2: 43.
917  Archivo3: 87.
918  Archivo4: 65.
919  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42
920 \layout Standard
921
922 Archivo1:.
923  Archivo2:.
924  Archivo3: 87.
925  Archivo4: 65.
926  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42 43
927 \layout Standard
928
929 Archivo1:.
930  Archivo2:.
931  Archivo3: 87.
932  Archivo4:.
933  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42 43 65
934 \layout Standard
935
936 Archivo1:.
937  Archivo2:.
938  Archivo3:.
939  Archivo4:.
940  Salida: 1 2 3 4 6 8 9 12 16 19 21 23 34 36 42 43 65 87
941 \layout Paragraph
942
943 Fin
944 \layout Standard
945
946 Finalmente, tengo en el archivo de salida el archivo original ordenado.
947 \layout Section
948
949 Alcance
950 \layout Standard
951
952 El algoritmo de ordenamiento es completamente genérico, ya que recibe un
953  puntero void como registro, su tamaño (para poder manipularlo sin conocer
954  su tipo) y una función de comparación, para poder comparar dos registros
955  (sin saber su tipo) a través de una relación de orden (descripta por dicha
956  función).
957 \layout Section
958
959 Decisiones de diseño.
960 \layout Standard
961
962 El algoritmo se eligió en base a una serie de razones y cuenta con una serie
963  de ventajas y desventajas.
964 \layout Itemize
965
966 El algoritmo es simple, tanto teóricamente como para implementar.
967 \layout Itemize
968
969 Tiene la desventaja de que puede llegar a usar muchos archivos temporales
970  y todos abiertos al mismo tiempo, pero considerando que el sistema operativo
971  en el que se utiliza suele manejar bien grandes cantidades de archivos
972  no es una desventaja importante.
973 \layout Itemize
974
975 Al usar un buffer intermedio, se puede controlar muy bien la cantidad de
976  memoria que utiliza y experimentar con distintos valores para analizar
977  los resultados.
978 \layout Itemize
979
980 El buffer ordenado se implementó con un árbol binario debido a que tiene
981  una buena relación entre velocidad de búsqueda y facilidad de implementación.
982  Al ser el principal determinante de la velocidad los accesos a disco no
983  se creyó necesario buscar una alternativa más rápida para mantener el buffer
984  ordenado en memoria, ya que no cambiaría de forma notable el tiempo total
985  del algoritmo.
986  Otras posibilidades hubieran sido cargar todo el buffer en memoria y ordenarlo
987  posteriormente (dependiendo del algoritmo de ordenamiento a utilizar puede
988  ser más o menos rápido que el árbol y más o menos complicado de implementar)
989  o hacer una búsqueda secuencial sobre un buffer desordenado (es más fácil
990  de implementar pero claramente más lento).
991  Una posible ventaja notable de leer el buffer primero y luego ordenarlo
992  en memoria es que se necesita un sólo acceso al disco para llenar el buffer,
993  mientras que al obtener uno a uno los valores puede generar muchos accesos
994  a disco.
995  Esto no debería ser muy notable ya que las funciones de acceso a archivos
996  de la biblioteca estándar de C poseen un buffer interno, por lo que los
997  accesos a disco probablemente sea muy poco aún cuando se obtienen uno a
998  uno.
999 \the_end