четверг, 19 июля 2012 г.

Бинарный поиск по сортированной таблице VK DBF

Пример

function Poisk(Table1: TVKDBFNTX; PoiskFields, PoiskKey: string; LowNo: Integer
  = 1; HighNo: Integer = 1): Boolean;
var
  LowNomer, HighNomer, mid, i: Integer;
  slist: TStringList;
  sKey: string;

  function GetFieldSumm: string;
  var
    i1: Byte;
  begin
    Result := '';
    for i1 := 0 to slist.Count - 1 do
      Result := Result + Table1.FieldByName(slist[i1]).AsString;
  end;

begin
  slist := TStringList.Create;
  slist.Text := stringReplace(PoiskFields, ';', #13#10, [rfReplaceAll]);
  HighNomer := IfThen(HighNo = 1, Table1.RecordCount, HighNo);
  LowNomer := LowNo;
  //функция AnsiCompareStr сравнивает 2 строки без учета регистра
  // возвращает значение -1 если S1S2
  Table1.SetTmpRecord(LowNomer);
  sKey := GetFieldSumm;
  if AnsiCompareText(sKey, PoiskKey) > 0 then
    Result := False
  else
  begin
    Table1.SetTmpRecord(HighNomer);
    sKey := GetFieldSumm;
    if AnsiCompareText(sKey, PoiskKey) < 0 then
      Result := False
    else
    begin
      while (HighNomer - LowNomer) > 1 do
      begin
        mid := (LowNomer + HighNomer) div 2;
        Table1.SetTmpRecord(mid);
        sKey := GetFieldSumm;
        if AnsiCompareText(sKey, PoiskKey) >= 0 then
          HighNomer := mid
        else
          LowNomer := mid;
      end;
      Table1.SetTmpRecord(LowNomer);
      sKey := GetFieldSumm;
      i := LowNomer;
      if AnsiCompareText(sKey, PoiskKey) < 0 then
      begin
        Table1.SetTmpRecord(HighNomer);
        sKey := GetFieldSumm;
        i := HighNomer;
      end;
      Table1.CloseTmpRecord;
      if AnsiCompareText(sKey, PoiskKey) = 0 then
      begin
        Result := True;
        Table1.RecNo := i;
      end
      else
        Result := False;
    end;
  end;
  FreeAndNil(slist);
end;

0 коммент.:

Отправить комментарий