rsvk/Xtra/QSortUnit.pas

140 lines
3.1 KiB
Plaintext
Raw Normal View History

2020-09-21 18:06:13 -05:00
unit QSortUnit;
{-------------------------------------------------------------------------------
Quick Sort unit
---------------
reSource (C) 1998 Victor K /97S66
Desc:
Sorts the index of a block.
This is the classic quick sort. Idiot proof, gueranteed to sort everytime.
Used for debugging. To confirm that any corrupted data is not the fault of
the sort.
Notes:
Uses a custom CompareStr routine that wraps around the end of the block.
-------------------------------------------------------------------------------}
(**) interface (**)
uses BWTCompressUnit, StructsUnit;
type
TQSortBlock = class
private
block: PBlock; // block that contains the data
index: PLongintBlock; // index to sort
block_length: longint; // data size in block
last_index: longint; // the index to the last piece of data in the block
public
constructor Create(const _block: PBlock; const _index: PLongintBlock; const _block_length: longint);
procedure Run;
end;
(**) implementation (**)
constructor TQSortBlock.Create(const _block: PBlock; const _index: PLongintBlock; const _block_length: longint);
begin
block := _block;
index := _index;
block_length := _block_length;
last_index := block_length-1;
end;
procedure TQSortBlock.Run;
function CompareStr(a, b: integer): integer;
var
times: byte;
first, index: longint;
begin
if (a <> b) then
begin
for times := 1 to 3 do
begin
{Take the later index to be the counter so that we know when we reach
the end}
if (a > b) then
first := a
else
first := b;
for index := first to last_index do
begin
if block^[a] < block^[b] then
begin
result := -1;
exit;
end
else
if block^[a] > block^[b] then
begin
result := 1;
exit;
end;
inc(a);
inc(b);
end;
{wrap indices around}
if (a = last_index+1) then
a := 0;
if (b = last_index+1) then
b := 0;
end;
{Equal comparison right to the end.
Shorter string, or the index closer to the end is greater}
if (a < b) then
result := -1
else
result := 1;
end
else
result := 0;
end; {Compare Str}
procedure QuickSort(const iLo, iHi: Integer);
var
Lo, Hi, Mid, T: Integer;
begin
Lo := iLo;
Hi := iHi;
Mid := index[(Lo + Hi) div 2];
repeat
while (CompareStr(index^[Lo], Mid) < 0) do inc(Lo);
while (CompareStr(index^[Hi], Mid) > 0) do dec(Hi);
{Swap}
if (Lo <= Hi) then
begin
T := index^[Lo];
index^[Lo] := index^[Hi];
index^[Hi] := T;
Inc(Lo);
Dec(Hi);
end;
until Lo > Hi;
if Hi > iLo then QuickSort(iLo, Hi);
if Lo < iHi then QuickSort(Lo, iHi);
end;
begin
QuickSort(0, last_index);
end;
end.