FUNCTION qqsort_real( VAR A :real_array ; left_1st,right_1st : INTEGER ) : BOOLEAN; { Original Author : Richard C. Singleton (Sept 17, 1968) Reference : Algorithm 347 ;Collected Algorithms of ACM. This function sorts the REAL array A ,from A[left_1st] to A[right_1st] , into ASCENDING order . To sort the entire array A set left_1st := 1 , and right_1st := N ,where N is the order of the array. If the value passed for left_1st is less than or equal to the value passed for right_1st then no sorting is done and the function returns false. The sort method used is similar to QUICKERSORT by R. S. Scowen (alg.271 ACM) which in turn is similar to the sort algorithm given by T.N.Hibbard and to C.A.R.Hoare's QUICKSORT ( alg.64 ACM ) .Unlike the original QUICKSORT it is not truly recursive. The initial segment of the array A is split into left and right "halves" composed of elements smaller and larger respectively than the median of the leftmost , middle and rightmost members of the initial segment.The smaller of the 2 "halves" is split similarly and the basic process repeated until a subsegment is produced with fewer than eleven elements.Once such a subsegment is formed it is sorted by a straight sinking insertion sort. The left and right bounds of the larger subsegment at each iteration are "stacked" in the arrays "left_bound" & "right_bound" and "popped off" once the smaller segment is fully sorted.Then the popped of segment is treated as was the initial segment etc. until the entire initial segment is done. Modified for Pascal/Z : October 1980 : Ray Penley September 82 : Greg Acland } CONST konst = 20; VAR middle, tempvar : REAL; left,right, newleft,newright, mid_index, element,pointer : INTEGER; left_bound, right_bound : ARRAY [0..konst] OF INTEGER; {Permit sorting up to 2EXP(konst + 1)-1 elements} alldone, past_midpoint, first,ok_array : BOOLEAN; BEGIN {$C-,M-,F-} left := left_1st; right := right_1st; pointer := 0; first := TRUE; alldone := FALSE; ok_array := left < right; IF ok_array THEN BEGIN REPEAT IF ((right-left) > 10) {IF : the segment has > 10 members} OR ( first ) {OR : it is the initial segment } THEN BEGIN {THEN : use splitting algorithm } IF first THEN first := FALSE; { step 1 = find the middle element of the segment } mid_index := (left+right) DIV 2; middle := A[mid_index]; newright := left; newleft := right; { step 2 = sort the left,middle and right elements of the segment } IF (A[left] > middle) THEN { swap them! } BEGIN A[mid_index] := A[left]; A[left] := middle; middle := A[mid_index] END; IF (A[right] < middle) THEN { swap them,then see if left element... } BEGIN A[mid_index] := A[right]; A[right] := middle; middle := A[mid_index]; IF (A[left] > middle) THEN { ..left needs swapping again!} BEGIN A[mid_index] := A[left]; A[left] := middle; middle := A[mid_index] END; END; { of : if A[right] < middle } { now the middle value is the median of left,middle and right values } past_midpoint := FALSE; REPEAT { step 3 = starting @ the rightmost end seek a value less than that of the middle element } REPEAT newleft := newleft - 1; UNTIL A[newleft] <= middle; {and from the left seek a value greater than the middle} REPEAT newright := newright + 1; UNTIL A[newright] >= middle; IF (newright <= newleft) THEN { the found values are in the wrong } BEGIN { halves so swap them! } tempvar := A[newleft]; A[newleft] := A[newright]; A[newright] := tempvar; END ELSE past_midpoint := TRUE; { when you pass the middle you have separated all elements > middle to the right and all those < middle to the left. } UNTIL past_midpoint; IF (newleft-left) > (right-newright) THEN { keep the smaller half } BEGIN { and stack the larger. } left_bound[pointer] := left; right_bound[pointer] := newleft; left := newright END ELSE BEGIN left_bound[pointer] := newright; right_bound[pointer] := right; right := newleft END; pointer := pointer + 1; END ELSE BEGIN { For each segment with < 11 members ( except the initial segment ) sort using a straight "sinking" insertion sort , by interchange of adjacent pairs.} FOR element := (left+1) TO right DO BEGIN middle := A[element]; newright := element - 1; IF A[newright] > middle THEN BEGIN REPEAT A[newright+1] := A[newright]; newright := newright - 1; UNTIL A[newright] <= middle; A[newright+1] := middle; END; END; { of : For element := (left + 1) ...} pointer := pointer - 1; IF pointer >= 0 THEN BEGIN left := left_bound[pointer]; right := right_bound[pointer]; END ELSE alldone := TRUE; END; { of : outermost if-then-else block } UNTIL alldone; { end of outermost repeat loop } END; { of : if ok_array } qqsort_real := ok_array; END; { of : function qqsort_real } {$C+,M+,F+}