Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
|
|
@ -0,0 +1,5 @@
|
|||
DEFINITION MODULE MSIterat;
|
||||
|
||||
PROCEDURE IterativeMergeSort( VAR a : ARRAY OF INTEGER);
|
||||
|
||||
END MSIterat.
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
IMPLEMENTATION MODULE MSIterat;
|
||||
|
||||
IMPORT Storage;
|
||||
|
||||
PROCEDURE IterativeMergeSort( VAR a : ARRAY OF INTEGER);
|
||||
VAR
|
||||
n, bufLen, len, endBuf : CARDINAL;
|
||||
k, nL, nR, b, h, i, j, startR, endR: CARDINAL;
|
||||
temp : INTEGER; (* array element *)
|
||||
pbuf : POINTER TO ARRAY CARDINAL OF INTEGER;
|
||||
BEGIN
|
||||
n := HIGH(a) + 1; (* length of array *)
|
||||
IF (n < 2) THEN RETURN; END;
|
||||
(* Sort blocks of length 2 by swapping elements if necessary.
|
||||
Start at high end of array; ignore a[0] if n is odd.*)
|
||||
k := n;
|
||||
REPEAT
|
||||
DEC(k, 2);
|
||||
IF (a[k] > a[k + 1]) THEN
|
||||
temp := a[k]; a[k] := a[k + 1]; a[k + 1] := temp;
|
||||
END;
|
||||
UNTIL (k < 2);
|
||||
IF (n = 2) THEN RETURN; END;
|
||||
|
||||
(* Set up a buffer for temporary storage when merging. *)
|
||||
(* TopSpeed Modula-2 doesn't seem to have dynamic arrays,
|
||||
so we use a workaround *)
|
||||
bufLen := n DIV 2;
|
||||
Storage.ALLOCATE( pbuf, bufLen*SIZE(INTEGER));
|
||||
|
||||
nR := 2; (* length of right-hand block when merging *)
|
||||
REPEAT
|
||||
len := 2*nR; (* maximum length of a merged block in this iteration *)
|
||||
k := n; (* start at the high end of the array *)
|
||||
WHILE (k > nR) DO
|
||||
IF (k >= len) THEN
|
||||
nL := nR; DEC(k, len);
|
||||
ELSE
|
||||
nL := k - nR; k := 0; END;
|
||||
|
||||
(* Merging 2 adjacent blocks, already sorted.
|
||||
k = start index of left block;
|
||||
nL, nR = lengths of left and right blocks *)
|
||||
startR := k + nL; endR := startR + nR;
|
||||
|
||||
(* Skip elements in left block that are already in correct place *)
|
||||
temp := a[startR]; (* first (smallest) element in right block *)
|
||||
j := k;
|
||||
WHILE (j < startR) AND (a[j] <= temp) DO INC(j); END;
|
||||
|
||||
endBuf := startR - j; (* length of buffer actually used *)
|
||||
IF (endBuf > 0) THEN (* if endBuf = 0 then already sorted *)
|
||||
(* Copy from left block to buffer, omitting elements
|
||||
that are already in correct place *)
|
||||
h := j;
|
||||
FOR b := 0 TO endBuf - 1 DO
|
||||
pbuf^[b] := a[h]; INC(h);
|
||||
END;
|
||||
(* Fill in values from right block or buffer *)
|
||||
b := 0;
|
||||
i := startR;
|
||||
(* j = startR - endBuf from above *)
|
||||
WHILE (b < endBuf) AND (i < endR) DO
|
||||
IF (pbuf^[b] <= a[i]) THEN
|
||||
a[j] := pbuf^[b]; INC(b)
|
||||
ELSE
|
||||
a[j] := a[i]; INC(i); END;
|
||||
INC(j);
|
||||
END;
|
||||
(* If now b = endBuf then the merge is complete.
|
||||
Else just copy the remaining elements in the buffer. *)
|
||||
WHILE (b < endBuf) DO
|
||||
a[j] := pbuf^[b]; INC(j); INC(b);
|
||||
END;
|
||||
END;
|
||||
END;
|
||||
nR := len;
|
||||
UNTIL (nR >= n);
|
||||
Storage.DEALLOCATE( pbuf, bufLen*SIZE(INTEGER));
|
||||
END IterativeMergeSort;
|
||||
|
||||
END MSIterat.
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
MODULE MSItDemo;
|
||||
(* Demo of iterative merge sort *)
|
||||
|
||||
IMPORT IO, Lib;
|
||||
FROM MSIterat IMPORT IterativeMergeSort;
|
||||
|
||||
(* Procedure to display the values in the demo array *)
|
||||
PROCEDURE Display( VAR a : ARRAY OF INTEGER);
|
||||
VAR
|
||||
j, nrInLine : CARDINAL;
|
||||
BEGIN
|
||||
nrInLine := 0;
|
||||
FOR j := 0 TO HIGH(a) DO
|
||||
IO.WrCard( a[j], 5); INC( nrInLine);
|
||||
IF (nrInLine = 10) THEN IO.WrLn; nrInLine := 0; END;
|
||||
END;
|
||||
IF (nrInLine > 0) THEN IO.WrLn; END;
|
||||
END Display;
|
||||
|
||||
(* Main routine *)
|
||||
CONST
|
||||
ArrayLength = 50;
|
||||
VAR
|
||||
arr : ARRAY [0..ArrayLength - 1] OF INTEGER;
|
||||
m : CARDINAL;
|
||||
BEGIN
|
||||
Lib.RANDOMIZE;
|
||||
FOR m := 0 TO ArrayLength - 1 DO arr[m] := Lib.RANDOM( 1000); END;
|
||||
IO.WrStr( 'Before:'); IO.WrLn; Display( arr);
|
||||
IterativeMergeSort( arr);
|
||||
IO.WrStr( 'After:'); IO.WrLn; Display( arr);
|
||||
END MSItDemo.
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
DEFINITION MODULE MergSort;
|
||||
|
||||
TYPE MSCompare = PROCEDURE( ADDRESS, ADDRESS) : INTEGER;
|
||||
TYPE MSGetNext = PROCEDURE( ADDRESS) : ADDRESS;
|
||||
TYPE MSSetNext = PROCEDURE( ADDRESS, ADDRESS);
|
||||
|
||||
PROCEDURE DoMergeSort( VAR start : ADDRESS;
|
||||
Compare : MSCompare;
|
||||
GetNext : MSGetNext;
|
||||
SetNext : MSSetNext);
|
||||
(*
|
||||
Procedures to be supplied by the caller:
|
||||
Compare(a1, a2) returns -1 if a1^ is to be placed before a2^;
|
||||
+1 if after; 0 if no priority.
|
||||
GetNext(a) returns address of next item after a^.
|
||||
SetNext(a, n) sets address of next item after a^ to n.
|
||||
If a^ is last item, then address of next item is NIL.
|
||||
It can be assumed that a, a1, a2 are not NIL.
|
||||
*)
|
||||
END MergSort.
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
IMPLEMENTATION MODULE MergSort;
|
||||
|
||||
PROCEDURE DoMergeSort( VAR start : ADDRESS;
|
||||
Compare : MSCompare;
|
||||
GetNext : MSGetNext;
|
||||
SetNext : MSSetNext);
|
||||
VAR
|
||||
p1, p2, q : ADDRESS;
|
||||
BEGIN
|
||||
(* If list has < 2 items, do nothing *)
|
||||
IF (start = NIL) THEN RETURN; END;
|
||||
p1 := GetNext( start); IF (p1 = NIL) THEN RETURN; END;
|
||||
|
||||
(* If list has only 2 items, we'll not use recursion *)
|
||||
p2 := GetNext( p1);
|
||||
IF (p2 = NIL) THEN
|
||||
IF (Compare( start, p1) > 0) THEN
|
||||
q := start; SetNext( p1, q); SetNext( q, NIL);
|
||||
start := p1;
|
||||
END;
|
||||
RETURN;
|
||||
END;
|
||||
|
||||
(* List has > 2 items: split list in half *)
|
||||
p1 := start;
|
||||
REPEAT
|
||||
p1 := GetNext( p1);
|
||||
p2 := GetNext( p2);
|
||||
IF (p2 <> NIL) THEN p2 := GetNext( p2); END;
|
||||
UNTIL (p2 = NIL);
|
||||
(* Now p1 points to last item in first half of list *)
|
||||
p2 := GetNext( p1); SetNext( p1, NIL);
|
||||
p1 := start;
|
||||
|
||||
(* Recursive calls to sort each half; p1 and p2 will be updated *)
|
||||
DoMergeSort( p1, Compare, GetNext, SetNext);
|
||||
DoMergeSort( p2, Compare, GetNext, SetNext);
|
||||
|
||||
(* Merge the sorted halves *)
|
||||
IF Compare( p1, p2) < 0 THEN
|
||||
start := p1; p1 := GetNext( p1);
|
||||
ELSE
|
||||
start := p2; p2 := GetNext( p2);
|
||||
END;
|
||||
q := start;
|
||||
WHILE (p1 <> NIL) AND (p2 <> NIL) DO
|
||||
IF Compare( p1, p2) < 0 THEN
|
||||
SetNext( q, p1); q := p1; p1 := GetNext( p1);
|
||||
ELSE
|
||||
SetNext( q, p2); q := p2; p2 := GetNext( p2);
|
||||
END;
|
||||
END;
|
||||
IF (p1 = NIL) THEN SetNext( q, p2) ELSE SetNext( q, p1) END;
|
||||
END DoMergeSort;
|
||||
END MergSort.
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
MODULE MergDemo;
|
||||
|
||||
IMPORT IO, Lib, MergSort;
|
||||
|
||||
TYPE PTestRec = POINTER TO TestRec;
|
||||
TYPE TestRec = RECORD
|
||||
Value : INTEGER;
|
||||
Next : PTestRec;
|
||||
END;
|
||||
|
||||
PROCEDURE Compare( a1, a2 : ADDRESS) : INTEGER;
|
||||
VAR
|
||||
p1, p2 : PTestRec;
|
||||
BEGIN
|
||||
p1 := a1; p2 := a2;
|
||||
IF (p1^.Value < p2^.Value) THEN RETURN -1
|
||||
ELSIF (p1^.Value > p2^.Value) THEN RETURN 1
|
||||
ELSE RETURN 0; END;
|
||||
END Compare;
|
||||
|
||||
PROCEDURE GetNext( a : ADDRESS) : ADDRESS;
|
||||
VAR
|
||||
p : PTestRec;
|
||||
BEGIN
|
||||
p := a; RETURN p^.Next;
|
||||
END GetNext;
|
||||
|
||||
PROCEDURE SetNext( a, n : ADDRESS);
|
||||
VAR
|
||||
p : PTestRec;
|
||||
BEGIN
|
||||
p := a; p^.Next := n;
|
||||
END SetNext;
|
||||
|
||||
(* Display the values in the linked list *)
|
||||
PROCEDURE Display( p : PTestRec);
|
||||
VAR
|
||||
nrInLine : CARDINAL;
|
||||
BEGIN
|
||||
nrInLine := 0;
|
||||
WHILE (p <> NIL) DO
|
||||
IO.WrCard( p^.Value, 5);
|
||||
p := p^.Next;
|
||||
INC( nrInLine);
|
||||
IF (nrInLine = 10) THEN IO.WrLn; nrInLine := 0; END;
|
||||
END;
|
||||
IF (nrInLine > 0) THEN IO.WrLn; END;
|
||||
END Display;
|
||||
|
||||
(* Main routine *)
|
||||
CONST ArraySize = 50;
|
||||
VAR
|
||||
arr : ARRAY [0..ArraySize - 1] OF TestRec;
|
||||
j : CARDINAL;
|
||||
start, p : PTestRec;
|
||||
BEGIN
|
||||
(* Fill values with random integers *)
|
||||
FOR j := 0 TO ArraySize - 1 DO
|
||||
arr[j].Value := Lib.RANDOM( 1000);
|
||||
END;
|
||||
(* Set up the links *)
|
||||
IF (ArraySize > 1) THEN (* FOR loop 0 TO -1 crashes program *)
|
||||
FOR j := 0 TO ArraySize - 2 DO
|
||||
arr[j].Next := ADR( arr[j + 1]);
|
||||
END;
|
||||
END;
|
||||
arr[ArraySize - 1].Next := NIL;
|
||||
(* Demonstrate merge sort on the linked list *)
|
||||
start := ADR( arr[0]);
|
||||
IO.WrStr( 'Before:'); IO.WrLn;
|
||||
Display( start);
|
||||
MergSort.DoMergeSort( start, Compare, GetNext, SetNext);
|
||||
IO.WrStr( 'After:'); IO.WrLn;
|
||||
Display( start);
|
||||
END MergDemo.
|
||||
Loading…
Add table
Add a link
Reference in a new issue