SOURCE FILE: qsort.pas
(* This is one of the quicksort's from the fourth edition of
"Pascal Plus Data Structures" by Dale and Lily. *)
(*********************************************************)
PROCEDURE Split
(VAR Info : ArrayType;
First : Integer;
Last : Integer;
VAR SplitPoint : IndexType);
(* Choose SplitVal and rearrange Info so that: *)
(* Info[First]..Info[SplitPoint - 1] <= SplitVal and *)
(* Info[SplitPoint] = SplitVal and *)
(* Info[SplitPoint + 1] .. Info[Last] > SplitVal. *)
VAR
SplitVal : ListElementType; (* value on which to split *)
SaveFirst : IndexType; (* original value of First *)
OnCorrectSide : Boolean;
BEGIN (* Split *)
(* SplitVal is chosen from the First array slot. *)
SplitVal := Info[First];
(* Set up for split loop. *)
SaveFirst := First;
First := First + 1;
(* Loop invariant: elements to the left of First are *)
(* less than or equal to SplitVal; elements to the *)
(* right of Last are greater than SplitVal. *)
REPEAT
OnCorrectSide := True;
WHILE OnCorrectSide DO
Case Compare (Info[First], SplitVal) OF
Greater : (* Info[First] is on the wrong side
of SplitVal *)
OnCorrectSide := False;
Less,
Equal : BEGIN
First := First + 1;
OnCorrectSide := First <= Last
(* First crossed Last? *)
END;
END; (* CASE *)
OnCorrectSide := First <= Last; (* First crossed Last? *)
WHILE OnCorrectSide DO
CASE Compare (Info[Last], SplitVal) OF
Less, (* Info[Last] is on the wrong side of splitVal *)
Equal : OnCorrectSide := False;
Greater : BEGIN
Last := Last - 1;
OnCorrectSide := First <= Last
END;
END; (* CASE *)
(* If on wrong side, Swap (Info[First], Info[Last]) *)
(* and update First and Last, *)
IF First < Last
THEN
BEGIN
Swap (Info[First], Info[Last]);
First := First + 1;
Last := Last - 1
END (* IF *)
UNTIL First > Last;
(* Set SplitPoint to place where the halves meet. *)
SplitPoint := Last;
(* Swap SplitVal with element at SplitPoint. *)
Swap (Info[SaveFirst], Info[SplitPoint])
END; (* Split *)
(*********************************************************)
PROCEDURE QuickSort
(VAR Info : ArrayType;
First : Integer;
Last : Integer);
VAR
SplitPoint : IndexType;
BEGIN (* QuickSort *)
IF First < Last (* General Case *)
THEN
BEGIN
(* Procedure Split chooses the splitting value and *)
(* rearranges the array so that: *)
(* Info[First] .. Info[SplitPoint - 1] <= SplitVal *)
(* Info[SplitPoint] = SplitVal *)
(* Info[SplitPoint + 1] .. Info[Last] > SplitVal. *)
Split (Info, First, Last, SplitPoint);
(* Sort the left "half." *)
QuickSort (Info, First, SplitPoint - 1);
(* Sort the right "half." *)
QuickSort (Info, SplitPoint + 1, Last)
END (* IF First < Last *)
(* ELSE Base Case: Do nothing. *)
END; (* QuickSort *)
(***************************************************************)