unit uutlAlgorithm; {$mode objfpc}{$H+} interface uses Classes, SysUtils, uutlInterfaces; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// generic TutlBinarySearch = class(TObject) public type IReadOnlyIndexer = specialize IutlReadOnlyIndexer; IComparer = specialize IutlComparer; private class function DoSearch( constref aIndexer: IReadOnlyIndexer; constref aComparer: IComparer; const aMin: Integer; const aMax: Integer; constref aItem: T; out aIndex: Integer): Boolean; public // search aItem in aIndexer using aComparer // aIndex is the index the item was found or should be inserted // returns TRUE when found, FALSE otherwise class function Search( constref aIndexer: IReadOnlyIndexer; constref aComparer: IComparer; constref aItem: T; out aIndex: Integer): Boolean; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function Supports(const aInstance: TObject; const aClass: TClass; out aObj): Boolean; overload; implementation //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function Supports(const aInstance: TObject; const aClass: TClass; out aObj): Boolean; begin result := Assigned(aInstance) and aInstance.InheritsFrom(aClass); if result then TObject(aObj) := aInstance else TObject(aObj) := nil; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TutlBinarySearch////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TutlBinarySearch.DoSearch( constref aIndexer: IReadOnlyIndexer; constref aComparer: IComparer; const aMin: Integer; const aMax: Integer; constref aItem: T; out aIndex: Integer): Boolean; var i, cmp: Integer; begin if (aMin <= aMax) then begin i := aMin + Trunc((aMax - aMin) / 2); cmp := aComparer.Compare(aItem, aIndexer.Items[i]); if (cmp = 0) then begin result := true; aIndex := i; end else if (cmp < 0) then result := DoSearch(aIndexer, aComparer, aMin, i-1, aItem, aIndex) else if (cmp > 0) then result := DoSearch(aIndexer, aComparer, i+1, aMax, aItem, aIndex); end else begin result := false; aIndex := aMin; end; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TutlBinarySearch.Search( constref aIndexer: IReadOnlyIndexer; constref aComparer: IComparer; constref aItem: T; out aIndex: Integer): Boolean; begin result := DoSearch(aIndexer, aComparer, 0, aIndexer.Count-1, aItem, aIndex); end; end.