``````{
> Can you show me any version of thew quick sort that you may have? I've
> never seen it and never used it before. I always used an insertion sort
> For anything that I was doing.

Here is one (long) non-recursive version, quite fast.
}

Type
_Compare  = Function(Var A, B) : Boolean;{ QuickSort Calls This }

{ --------------------------------------------------------------- }
{ QuickSort Algorithm by C.A.R. Hoare.  Non-Recursive adaptation  }
{ from "ALGORITHMS + DATA STRUCTURES = ProgramS" by Niklaus Wirth }
{ Prentice-Hall, 1976. Generalized For unTyped arguments.   }
{ --------------------------------------------------------------- }

Procedure QuickSort(V      : Pointer;   { To Array of Records }
Cnt    : Word;      { Record Count        }
Len    : Word;      { Record Length       }
ALessB : _Compare); { Compare Function    }

Type
SortRec = Record
Lt, Rt : Integer
end;

SortStak = Array [0..1] of SortRec;

Var
StkT,
StkM,
Ki, Kj,
M       : Word;
Rt, Lt,
I, J    : Integer;
Ps      : ^SortStak;
Pw, Px  : Pointer;

Procedure Push(Left, Right : Integer);
begin
Ps^[StkT].Lt := Left;
Ps^[StkT].Rt := Right;
Inc(StkT);
end;

Procedure Pop(Var Left, Right : Integer);
begin
Dec(StkT);
Left  := Ps^[StkT].Lt;
Right := Ps^[StkT].Rt;
end;

begin {QSort}
if (Cnt > 1) and (V <> Nil) Then
begin
StkT := Cnt - 1;    { Record Count - 1 }
Lt   := 1;          { Safety Valve    }

{ We need a stack of Log2(n-1) entries plus 1 spare For safety }

Repeat
StkT := StkT SHR 1;
Inc(Lt);
Until StkT = 0; { 1+Log2(n-1) }

StkM := Lt * SizeOf(SortRec) + Len + Len; { Stack Size + 2 Records }

GetMem(Ps, StkM);   { Allocate Memory    }

if Ps = Nil Then
RunError(215); { Catastrophic Error }

Pw := @Ps^[Lt];   { Swap Area Pointer  }
Px := Ptr(Seg(Pw^), Ofs(Pw^) + Len); { Hold Area Pointer  }

Lt := 0;
Rt := Cnt - 1;  { Initial Partition  }

Push(Lt, Rt);   { Push Entire Table  }

While StkT > 0 Do
begin  { QuickSort Main Loop }
Pop(Lt, Rt);   { Get Next Partition  }
Repeat
I := Lt; J := Rt;  { Set Work Pointers }

{ Save Record at Partition Mid-Point in Hold Area }
M := (LongInt(Lt) + Rt) div 2;
Move(Ptr(Seg(V^), Ofs(V^) + M * Len)^, Px^, Len);

{ Get Useful Offsets to speed loops }
Ki := I * Len + Ofs(V^);
Kj := J * Len + Ofs(V^);

Repeat
{ Find Left-Most Entry >= Mid-Point Entry }
While ALessB(Ptr(Seg(V^), Ki)^, Px^) Do
begin
Inc(Ki, Len);
Inc(I)
end;

{ Find Right-Most Entry <= Mid-Point Entry }
While ALessB(Px^, Ptr(Seg(V^), Kj)^) Do
begin
Dec(Kj, Len);
Dec(J)
end;

{ if I > J, the partition has been exhausted }
if I <= J Then
begin
if I < J Then  { we have two Records to exchange }
begin
Move(Ptr(Seg(V^), Ki)^, Pw^, Len);
Move(Ptr(Seg(V^), Kj)^, Ptr(Seg(V^), Ki)^, Len);
Move(Pw^, Ptr(Seg(V^), Kj)^, Len);
end;

Inc(I);
Dec(J);
Inc(Ki, Len);
Dec(Kj, Len);
end; { if I <= J }
Until I > J;  { Until All Swaps Done }

{ We now have two partitions.  At left are all Records }
{ < X, and at right are all Records > X.  The larger   }
{ partition is stacked and we re-partition the residue }
{ Until time to pop a deferred partition.              }

if (J - Lt) < (Rt - I) Then { Right-Most Partition is Larger }
begin
if I < Rt Then
Push(I, Rt); { Stack Right Side }
Rt := J;    { Resume With Left }
end
else  {  Left-Most Partition is Larger }
begin
if Lt < J Then
Push(Lt, J); { Stack Left Side   }
Lt := I;    { Resume With Right }
end;

Until Lt >= Rt;  { QuickSort is now Complete }
end;
FreeMem(Ps, StkM);   { Free Stack and Work Areas }
end;
end; {QSort}

``````