home *** CD-ROM | disk | FTP | other *** search
- {This is a sorting procedure using the natural merge sort to sort files
- of items larger than can be held in memory. It is really a demonstration
- of the technique; you'll need to fill in infotype and keytype, and the
- interface providing the appropriate filenames.
-
- I've had several requests for this kind of algorithm. Unfortunately, I
- can't provide you with a compilable module per se, because that's less
- applicable. This is a general purpose example, patterned after a routine
- by David F. Moffat. Best wishes, Glenn Brooke 11/22/85
- }
-
- type
- infotype = ...; {whatever you like}
- keytypte = ...; { "}
- item = record {each file element}
- key : keytype; {'key' to the data}
- info : infotye; {information to be stored}
- end;
- itemfile = file of item; {a sequence of these items}
-
- var
- F : itemfile;
- i : item;
-
- procedure Sort(var F : itemfile);
- {sort the file F into ascending order, using natural merge sort}
-
- var
- runs := 0..maxint; {# of sequences of ascending order values}
- temp1, temp2 : itemfile; {these hold runs of items that are from F, to}
- {be compared and merged back into F}
- endrun : boolean; {true only at end of run}
-
- procedure copyitem(var source : itemfile;
- var dest : itemfile);
-
- {copy a single value from source to dest, setting global endrun to true
- if this value is the last in an ascending sequence (run)}
- var i : item; {value being copied}
- begin {copyitem}
- read(source,i);
- write(dest,i);
- {check for end of run}
- if eof(source) then endrun := true else endrun := (i.key > source@.key)
- end; {copyitem}
-
- procedure copyrun(var source : itemfile;
- var dest : itemfile);
- {copy a run (ascending sequence) of values from source to dest}
- begin
- repeat
- copyitem(source, dest)
- until endrun {endrun set by copyitem}
- end; {copyrun}
-
- procedure splitup(var F : itemfile;
- var temp1 : itemfile;
- var temp2 : itemfile);
- {copy the successive runs from F into the files temp1, temp2, alternating
- whole runs between the two files.}
- begin
- reset(F);
- rewrite(temp1);
- rewrite(temp2);
- repeat
- copyrun(F, temp1);
- if not eof(F) then copyrun(F, temp2)
- until eof(F)
- end; {splitup}
-
- procedure MergeRuns(var temp1 : itemfile;
- var temp2 : itemfile;
- var F : itemfile);
- {merge the next pair of runs from temp1 to temp2 into a single and
- longer run, back into F}
- begin
- repeat
- if temp1@.key < temp2@.key then
- begin {take from temp1}
- copyitem(temp1, F);
- {the run in temp1 could be the shorter one}
- if endrun then copyrun(temp2, F)
- end
- else
- begin {take from temp2}
- copyitem(temp2, F);
- if endrun then copyrun(temp1,F)
- end
- until endrun
- end; {mergeruns}
-
- procedure Recombine(var temp1 : itemfile;
- var temp2 : itemfile;
- var F : itemfile);
- {merge all pairs of runs from temp1 and temp2, combining them into
- successive (and longer) runs in F. Count the number of runs in F}
- begin
- reset(temp1);
- reset(temp2);
- rewrite(F);
-
- {merge and count pairs of run}
- while not eof(temp1) and not eof(temp2) do
- begin {each pair}
- mergeruns(temp1,temp2,F);
- runs := succ(runs)
- end; {each pair}
-
- {there may be some runs left in one of the files}
- while not eof(temp1) do
- begin
- copyrun(temp1,F);
- runs := succ(runs)
- end;
- while not eof(temp2) do
- begin
- copyrun(temp2,F);
- runs := succ(runs)
- end
- end; {recombine}
-
- begin {sort}
- {split the files into successive runs, then recombine paris of runs
- into longer runs, until one 1 run}
- repeat
- splitup(F, temp1, temp2);
- runs := 0;
- recombine(temp1, temp2, F)
- until runs = 1
- end; {sort}