Browse Source

* [uutlGenerics] TutlList<T>: declare Sort() and required generics

* [uutlAlgorithm] range errors in QuickSort, avoid double-free by using IutlArray.Exchange
* [uutlComparer] TutlReverseComparer: invert an arbitrary IutlComparer
master
Martok 7 years ago
parent
commit
957fb0a20d
4 changed files with 64 additions and 13 deletions
  1. +10
    -12
      uutlAlgorithm.pas
  2. +38
    -0
      uutlComparer.pas
  3. +15
    -1
      uutlGenerics.pas
  4. +1
    -0
      uutlInterfaces.pas

+ 10
- 12
uutlAlgorithm.pas View File

@@ -180,21 +180,19 @@ class procedure TutlQuickSort.DoSort(
aHigh: Integer);
var
lo, hi: Integer;
p, tmp: T;
p: T;
begin
repeat
while (aLow < aHigh) do begin
lo := aLow;
hi := aHigh;
p := aArray[(aLow + aHigh) div 2];
repeat
while (aComparer.Compare(p, aArray[lo]) > 0) do
while (aComparer.Compare(p, aArray[lo]) > 0) and (lo < aHigh) do
lo := lo + 1;
while (aComparer.Compare(p, aArray[hi]) < 0) do
while (aComparer.Compare(p, aArray[hi]) < 0) and (hi > aLow) do
hi := hi - 1;
if (lo <= hi) then begin
tmp := aArray[lo];
aArray[lo] := aArray[hi];
aArray[hi] := tmp;
aArray.Exchange(lo, hi);
lo := lo + 1;
hi := hi - 1;
end;
@@ -209,7 +207,7 @@ begin
DoSort(aArray, aComparer, lo, aHigh);
aHigh := hi;
end;
until (aLow >= aHigh);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -225,14 +223,14 @@ begin
if not Assigned(aArray) then
raise EArgumentNilException.Create('aArray');

repeat
while (aLow < aHigh) do begin
lo := aLow;
hi := aHigh;
p := aArray[(aLow + aHigh) div 2];
repeat
while (aComparer.Compare(p, aArray[lo]) > 0) do
while (aComparer.Compare(p, aArray[lo]) > 0) and (lo < aHigh) do
lo := lo + 1;
while (aComparer.Compare(p, aArray[hi]) < 0) do
while (aComparer.Compare(p, aArray[hi]) < 0) and (hi > aLow) do
hi := hi - 1;
if (lo <= hi) then begin
tmp := aArray[lo];
@@ -252,7 +250,7 @@ begin
DoSort(aArray, aComparer, lo, aHigh);
aHigh := hi;
end;
until (aLow >= aHigh);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


+ 38
- 0
uutlComparer.pas View File

@@ -111,6 +111,25 @@ type
{$ENDIF}
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlReverseComparer<T> = class(
TInterfacedObject,
specialize IutlEqualityComparer<T>,
specialize IutlComparer<T>)

public type
IComparer = specialize IutlComparer<T>;

private
fComparer: IComparer;

public
function EqualityCompare(constref i1, i2: T): Boolean;
function Compare(constref i1, i2: T): Integer;

constructor Create(aComparer: IComparer);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
operator <(const i1, i2: TObject): Boolean; inline;
operator >(const i1, i2: TObject): Boolean; inline;
@@ -244,5 +263,24 @@ begin
end;
{$ENDIF}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlReverseComparer///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlReverseComparer.EqualityCompare(constref i1, i2: T): Boolean;
begin
Result:= fComparer.EqualityCompare(i1, i2);
end;

function TutlReverseComparer.Compare(constref i1, i2: T): Integer;
begin
Result:= - fComparer.Compare(i1, i2);
end;

constructor TutlReverseComparer.Create(aComparer: IComparer);
begin
inherited Create;
fComparer:= aComparer;
end;

end.


+ 15
- 1
uutlGenerics.pas View File

@@ -207,10 +207,16 @@ type
generic TutlList<T> = class(
specialize TutlCustomList<T>)

private type
TQuickSortImpl = specialize TutlQuickSort<T>;
IComparer = TQuickSortimpl.IComparer;
TReverseComp = specialize TutlReverseComparer<T>;
public type
TEqualityComparer = specialize TutlEqualityComparer<T>;

public
procedure Sort(aComparer: IComparer; const aReverse: boolean = false);

constructor Create(const aOwnsItems: Boolean);
end;

@@ -1157,7 +1163,7 @@ begin
System.Move(p1^, tmp{%H-}, SizeOf(T));
System.Move(p2^, p1^, SizeOf(T));
System.Move(tmp, p2^, SizeOf(T));
FillByte(tmp, SizeOf(tmp), 0)
FillByte(tmp, SizeOf(tmp), 0);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1278,6 +1284,14 @@ end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlList//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlList.Sort(aComparer: IComparer; const aReverse: boolean);
begin
if aReverse then
aComparer:= TReverseComp.Create(aComparer);
TQuickSortImpl.Sort(Self, aComparer);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlList.Create(const aOwnsItems: Boolean);
begin


+ 1
- 0
uutlInterfaces.pas View File

@@ -92,6 +92,7 @@ type
['{D3618E88-3BF7-4E63-850F-6893A334564A}']
procedure SetCount(const aValue: Integer);
procedure SetItem(const aIndex: Integer; aItem: T);
procedure Exchange(const aIndex1, aIndex2: Integer);

property Count: Integer read GetCount write SetCount;
property Items[const aIndex: Integer]: T read GetItem write SetItem; default;


Loading…
Cancel
Save