UNIT Sort; { These sort routines are for arrays of Integers. Count is the maximum } { number of items in the array. } {****************************************************************************} INTERFACE {****************************************************************************} FUNCTION BinarySearch (VAR A; X : Integer; Count : Integer) : Integer; PROCEDURE BubbleSort (VAR A; Count : Integer); {slow} PROCEDURE CombSort (VAR A; Count : Integer); PROCEDURE QuickSort (VAR A; Count : Integer); {fast} FUNCTION SequentialSearch (VAR A; X : Integer; Count : Integer) : Integer; PROCEDURE ShellSort (VAR A; Count : Integer); {moderate} {****************************************************************************} IMPLEMENTATION {****************************************************************************} TYPE SortArray = ARRAY[0..0] OF Integer; {****************************************************************************} { } { Local Procedures and Functions } { } {****************************************************************************} PROCEDURE Swap (VAR A, B : Integer); VAR C : Integer; BEGIN C := A; A := B; B := C; END; {****************************************************************************} { } { Global Procedures and Functions } { } {****************************************************************************} FUNCTION BinarySearch (VAR A; X : Integer; Count : Integer) : Integer; VAR High, Low, Mid : Integer; BEGIN Low := 1; High := Count; WHILE High >= Low DO BEGIN Mid := Trunc(High + Low) DIV 2; IF X > SortArray(A)[mid] THEN Low := Mid + 1 ELSE IF X < SortArray(A)[Mid] THEN High := Mid - 1 ELSE High := -1; END; IF High = -1 THEN BinarySearch := Mid ELSE BinarySearch := 0; END; {****************************************************************************} PROCEDURE BubbleSort (VAR A; Count : Integer); VAR i, j : Integer; BEGIN FOR i := 2 TO Count DO FOR j := Count DOWNTO i DO IF SortArray(A)[j-1] > SortArray(A)[j] THEN Swap(SortArray(A)[j],SortArray(A)[j-1]); END; {****************************************************************************} PROCEDURE CombSort (VAR A; Count : Integer); { The combsort is an optimised version of the bubble sort. It uses a } { decreasing gap in order to compare values of more than one element } { apart. By decreasing the gap the array is gradually "combed" into } { order ... like combing your hair. First you get rid of the large } { tangles, then the smaller ones ... } { There are a few particular things about the combsort. } { Firstly, the optimal shrink factor is 1.3 (worked out through a } { process of exhaustion by the guys at BYTE magazine). Secondly, by } { never having a gap of 9 or 10, but always using 11, the sort is } { faster. } { This sort approximates an n log n sort - it's faster than any other } { sort I've seen except the quicksort (and it beats that too sometimes). } { The combsort does not slow down under *any* circumstances. In fact, on } { partially sorted lists (including *reverse* sorted lists) it speeds up.} CONST ShrinkFactor = 1.3; { Optimal shrink factor ... } VAR Gap, i, Temp : Integer; Finished : Boolean; BEGIN Gap := Trunc(ShrinkFactor); REPEAT Finished := TRUE; Gap := Trunc(Gap/ShrinkFactor); IF Gap < 1 THEN { Gap must *never* be less than 1 } Gap := 1 ELSE IF Gap IN [9,10] THEN { Optimises the sort ... } Gap := 11; FOR i := 1 TO (Count - Gap) DO IF SortArray(A)[i] < SortArray(A)[i+gap] THEN BEGIN Swap(SortArray(A)[i],SortArray(A)[i + Gap]); Finished := FALSE; END; UNTIL (Gap = 1) AND Finished; END; {****************************************************************************} PROCEDURE QuickSort (VAR A; Count : Integer); {**************************************************************************} PROCEDURE PartialSort(LowerBoundary, UpperBoundary : Integer; VAR A); VAR ii, l1, r1, i, j, k : Integer; BEGIN k := (SortArray(A)[LowerBoundary] + SortArray(A)[UpperBoundary]) DIV 2; i := LowerBoundary; j := UpperBoundary; REPEAT WHILE SortArray(A)[i] < k DO Inc(i); WHILE k < SortArray(A)[j] DO Dec(j); IF i <= j THEN BEGIN Swap(SortArray(A)[i],SortArray(A)[j]); Inc(i); Dec(j); END; UNTIL i > j; IF LowerBoundary < j THEN PartialSort(LowerBoundary,j,A); IF i < UpperBoundary THEN PartialSort(UpperBoundary,i,A); END; {*************************************************************************} BEGIN PartialSort(1,Count,A); END; {****************************************************************************} FUNCTION SequentialSearch (VAR A; X : Integer; Count : Integer) : Integer; VAR i : Integer; BEGIN FOR i := 1 TO Count DO IF X = Sortarray(A)[i] THEN BEGIN SequentialSearch := i; Exit; END; SequentialSearch := 0; END; {****************************************************************************} PROCEDURE ShellSort (VAR A; Count : Integer); VAR Gap, i, j, k : Integer; BEGIN Gap := Count DIV 2; WHILE (gap > 0) DO BEGIN FOR i := (Gap + 1) TO Count DO BEGIN j := i - Gap; WHILE (j > 0) DO BEGIN k := j + gap; IF (SortArray(A)[j] <= SortArray(A)[k]) THEN j := 0 ELSE Swap(SortArray(A)[j],SortArray(A)[k]); j := j - Gap; END; END; Gap := Gap DIV 2; END; END; {*****************************************************************************} END.