AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Binäre Suche rekursiv

Ein Thema von CalganX · begonnen am 18. Sep 2006 · letzter Beitrag vom 18. Sep 2006
Antwort Antwort
CalganX

Registriert seit: 21. Jul 2002
Ort: Bonn
5.403 Beiträge
 
Turbo Delphi für Win32
 
#1

Binäre Suche rekursiv

  Alt 18. Sep 2006, 18:43
Hi,
ich versuche gerade just for fun eine binäre Suche zu programmieren, doch irgendwie funktioniert bei mir die Rekursion nicht richtig.

Delphi-Quellcode:
type
  TEntry = record
    n_name: string;
    v_name: string;
  end;
  TList = array[1..lg] of TEntry;

function binsuche(nname: string; list: TList; index: integer): integer;
var
  tdx: integer;
begin
  if list[index].n_name = nname then begin
    Result := index;
    Exit;
  end;

  if list[index].n_name > nname then
    tdx := index div 2
  else
    tdx := (index + lg) div 2;

  if tdx <> index then
    Result := binsuche(nname, list, tdx)
  else
    Result := -1;
end;
Ich habe ein Testfeld mal recht willkürlich belegt:

Delphi-Quellcode:
procedure belege(var list: TList);
begin
  List[1].n_name := 'Adams';
  List[1].v_name := 'Douglas';

  List[2].n_name := 'Bauer';
  List[2].v_name := 'Joachim';

  List[3].n_name := 'Daniels';
  List[3].v_name := 'Jack';

  List[4].n_name := 'Gorbatschow';
  List[4].v_name := 'Michail';

  List[5].n_name := 'Müller';
  List[5].v_name := 'Karl-Otto';
end;
Wenn ich nun nach dem fünften Eintrag suche (Müller), dann findet meine binäre Suche keinen Eintrag. Woran kann das liegen?

Chris
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#2

Re: Binäre Suche rekursiv

  Alt 18. Sep 2006, 18:56
Hallo Chris,

die Signatur deiner Funktion ist falsch, du musst die upper und die lower bound für die zu untersuchende Liste übergeben. Im Rumpf vergleichst du mit dem mittleren Element der Liste und veränderst die entsprechende Grenze, wenn die Suche noch nicht erfolgreich war. Das Abbruchkriterium ist dann lBound > uBound.

Viel Spaß

marabu
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.275 Beiträge
 
Delphi 10.4 Sydney
 
#3

Re: Binäre Suche rekursiv

  Alt 18. Sep 2006, 19:20
Hallo,

just gestern habe ich es doch mal geschafftm
meine BinSearch fertigzustellen.

Sie arbeitet mit TList, aber abgesehen von der Start-Grenze 0,
sollte es doch auch so klappen.

Das ganze sieht etwas komplizierter aus als Code aus dem Netz,
z.B. das

Delphi-Quellcode:
iCompareResult:= BusinessObject.Compare(
  theSearchBusinessObject, theSearchMethod);
Hintergrund ist, dass die BinSearch verschiedene Suchkriterien hat.
Natürlich muss die Liste vorher nach dem jeweiligen Koriteriem sortiert werden.

Das TBusinessObject ist mein Basisobjekt, was eine abstrakte Compare-Methode enthält.

Delphi-Quellcode:
{
name:
  InternalBinSearch
usage:
  internal bin search method
parameter:
  theLow          - low order
  theHigh        - high order
  theSearchMethod - search method
return parameter:
return:
  NIL, if not found
notes:
}

function TBusinessObjectList.InternalBinSearch(
  const theLow, theHigh: Integer;
  const theSearchBusinessObject: TBusinessObject;
  const theSearchMethod: Integer): TBusinessObject;
var
  iMiddle : Integer;
  iNewLow : Integer;
  iNewHigh : Integer;
  iCompareResult : Integer;
  BusinessObject : TBusinessObject;
begin
  Result:= NIL;

  if theLow>theHigh then Exit;

  iMiddle:= theLow + ((theHigh-theLow) div 2);

  BusinessObject:= Items[iMiddle];
  iCompareResult:= BusinessObject.Compare(
    theSearchBusinessObject, theSearchMethod);

  if iCompareResult=0 then
  begin
   { we got it :) }
    Result:= BusinessObject;
    Exit;
  end;

  if iCompareResult=-1 then
  begin
   { if the current object is smaller than we need
     we continue searching at the right side (the higher side) }

    iNewLow := iMiddle+1;
    iNewHigh := theHigh;
  end
  else
  begin
   { if the current object is smaller than we need
     we continue searching at the right side (the higher side) }

    iNewLow := theLow;
    iNewHigh := iMiddle-1;
  end;

  Result:= InternalBinSearch(iNewLow, iNewHigh,
    theSearchBusinessObject, theSearchMethod);
end; { TBusinessObjectList.InternalBinSearch }
Der Aufruf erfolgt über
Delphi-Quellcode:
{
name:
  BinSearch
usage:
  internal bin search method
parameter:
  theLow          - low order
  theHigh        - high order
  theSearchMethod - search method
return parameter:
return:
  NIL, if not found
notes:
}

function TBusinessObjectList.BinSearch(
  theSearchBusinessObject: TBusinessObject;
  const theSearchMethod: Integer): TBusinessObject;
begin
  Result:= InternalBinSearch(0, Count-1,
    theSearchBusinessObject, theSearchMethod);
end; { TBusinessObjectList.BinSearch }

Heiko
Heiko
  Mit Zitat antworten Zitat
CalganX

Registriert seit: 21. Jul 2002
Ort: Bonn
5.403 Beiträge
 
Turbo Delphi für Win32
 
#4

Re: Binäre Suche rekursiv

  Alt 18. Sep 2006, 19:26
Hi marabu,

danke für den Tipp. Mein Code sieht jetzt so aus:
Delphi-Quellcode:
function binsuche(nname: string; list: TList; lbound, ubound: integer): integer;
var
  tdx: integer;
begin
  if lbound > ubound then begin
    Result := -1;
    Exit;
  end;

  tdx := lbound + ( (ubound - lbound) div 2 );

  if list[tdx].n_name = nname then begin
    Result := tdx;
    Exit;
  end;

  if list[tdx].n_name > nname then
    Result := binsuche(nname, list, 1, tdx)
  else
    Result := binsuche(nname, list, tdx, ubound);
end;
Wenn ich nun nach dem letzten Element der Liste suche, bekomme ich einen Stack Overflow um die Ohren gehauen und das Programm beendet sich (ist ein Konsolenprogramm).

@hoika: Danke, ich guck mir den Code mal an und vergleiche und versuche den Fehler zu finden.

Chris


Edit:
Fehler schon gefunden.
Ich habe die Rekursionsgrenzen etwas verändert:
Delphi-Quellcode:
  if list[tdx].n_name > nname then
    Result := binsuche(nname, list, 1, tdx-1)
  else
    Result := binsuche(nname, list, tdx+1, ubound);
So funktioniert's. Danke für eure Hilfe.
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#5

Re: Binäre Suche rekursiv

  Alt 18. Sep 2006, 20:17
Chris,

du solltest noch etwas sorgfältiger testen. Bei der binären Suche veränderst du die obere oder die untere Grenze - eine konstante untere Grenze 1 sieht irgendwie sehr willkürlich aus.

Delphi-Quellcode:
if list[tdx].n_name > nname
  then Result := binsuche(nname, list, lBound, Pred(tdx))
  else Result := binsuche(nname, list, Succ(tdx), uBound);
Und zumindest für die Suche eines Strings könntest du die Funktion noch verallgemeinern.

Gute Nacht

marabu
  Mit Zitat antworten Zitat
CalganX

Registriert seit: 21. Jul 2002
Ort: Bonn
5.403 Beiträge
 
Turbo Delphi für Win32
 
#6

Re: Binäre Suche rekursiv

  Alt 18. Sep 2006, 20:29
Hi marabu,

Zitat von marabu:
du solltest noch etwas sorgfältiger testen. Bei der binären Suche veränderst du die obere oder die untere Grenze - eine konstante untere Grenze 1 sieht irgendwie sehr willkürlich aus.
Stimmt, jetzt wo du's sagst.

Zitat:
Und zumindest für die Suche eines Strings könntest du die Funktion noch verallgemeinern.
Naja, es ging mir jetzt primär darum zu gucken, warum ich das in meiner Info-Klausur nicht richtig gemacht habe (das regt mich schon den ganzen Tag auf, dass mir das meine 15 Punkte versaut hat ). Und da war es halt dieses Verzeichnis.
Verallgemeinern kann man das sicher noch... Aber spätestens wenn es darum geht, für einen Vergleich, einen Methodenzeiger auf eine Callback-Funktion zu setzen, denke ich sollte es erstmal reichen. Und an dieser Stelle reicht es mir auch erstmal.

Danke für deine Hilfe,
Chris
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:22 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz