Mirror

Binary search on an alphasorted TListView (Views: 713)


Problem/Question/Abstract:

How to do a binary search on an alphasorted TListView

Answer:

If you want to use a fast searching algorithm (binary search for example) the listview has to be sorted on the column you do the duplicate check on. If it is not sorted you have to use the listviews FindCaption or FindData method, which does a linear search. To sort a listview use its AlphaSort or CustomSort methods.

A binary search on a alphasorted listview for a caption would be something like this (untested!):

{
Function ListviewBinarySearch

Parameters:

listview:
listview to search, assumed to be sorted, must be <> nil.

Item:
item caption to search for, cannot be empty

index:
returns the index of the found item, or the index where the item should be inserted if it is not already in the list. Returns True if there is an item with the passed caption in the list, false otherwise.

Description:
Uses a binary search and assumes that the listview is sorted ascending on the caption of the listitems. The search is case-sensitive, like the default alpha-sort routine used by the TListview class.

Note:
We use the lstrcmp function for string comparison since it is the function used by the default alpha sort routine. If the listview is sorted by another means (e.g. OnCompare event) this needs to be changed, the comparison method used must always be the same one used to sort the listview, or the search will not work!

Error Conditions: none
Created: 31.10.99 by P. Below
}

function ListviewBinarySearch(listview: TListview; const Item: string; var index:
  Integer): Boolean;
var
  first, last, pivot, res: Integer;
begin
  Assert(Assigned(listview));
  Assert(Length(item) > 0);
  Result := false;
  index := 0;
  if listview.items.count = 0 then
    Exit;
  first := 0;
  last := listview.items.count - 1;
  repeat
    pivot := (first + last) div 2;
    res := lstrcmp(PChar(item), Pchar(listview.items[pivot].caption));
    if res = 0 then
    begin
      { Found the item, return its index and exit. }
      index := pivot;
      result := true;
      Break;
    end
    else if res > 0 then
    begin
      { Item is larger than item at pivot }
      first := pivot + 1;
    end
    else
    begin
      { Item is smaller than item at pivot }
      last := pivot - 1;
    end;
  until
    last < first;
  index := first;
end;

<< Back to main page