* [uutlAlgorithm] range errors in QuickSort, avoid double-free by using IutlArray.Exchange * [uutlComparer] TutlReverseComparer: invert an arbitrary IutlComparermaster
| @@ -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; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -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. | |||
| @@ -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 | |||
| @@ -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; | |||