Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Liste von Arrays (https://www.delphipraxis.net/189066-liste-von-arrays.html)

mucki64 29. Apr 2016 16:30


Liste von Arrays
 
Hallo,

ich suche nach einer geeigneten Datenstruktur, um in einem rekursiven Programm Strings einzusammeln.
Die Methode sollte einen String, besser eine TStringList oder ein Array of Strings zurückgeben.
Dabei müssen Teillisten zusammengefaßt werden. Wie geht das elegant? Hier der Algorithmus:

Delphi-Quellcode:
function TBaum.Traversiere(Z: TElement): TStringList;
var Inhalt: TStringList;

Begin
     Inhalt := TStringList.Create;
     IF Z<>NIL Then
     Begin
          Inhalt.Add(Traversiere(Z.gibSohn(ToLinks)));   // geht nicht, da Add nur einen String anhängt
          if Z<>Wurzel then
               Inhalt.Add(Z.gibInhalt);
          Inhalt.Add(Trraversiere(Z.gibSohn(ToRechts)));
     End;
Traversiere := Inhalt;
End;

bra 29. Apr 2016 16:35

AW: Liste von Arrays
 
Die TStringList sollte als var-Parameter übergeben werden, sonst hast du hinterher massig TStringLists, die im Speicher rumhängen.

Delphi-Quellcode:
procedure TBaum.Traversiere(Z: TElement; var AList: TStringList);
...

Blup 29. Apr 2016 17:16

AW: Liste von Arrays
 
Die Direktive "var" ist hier überflüssig, da Objektvariablen nur die Referenz(Pointer) auf das eigentlich Objekt enthalten.

haentschman 29. Apr 2016 17:19

AW: Liste von Arrays
 
Moin...:P

Denke auch an die Freigabe der TStringlist Inhalt. Bedenke, das du bei jedem rekursiven Aufruf eine neue Instanz dazu bekommst (bekommen würdest).
Besser: Die Liste die den Result repräsentiert außerhalb der Funktion verwalten(wie schon erwähnt z.B. als Parameter übergeben oder als privates Feld)

Sir Rufo 29. Apr 2016 19:49

AW: Liste von Arrays
 
Eine Möglichkeit (garantiert ohne MemLeaks) wäre
Delphi-Quellcode:
function TBaum.Traversiere( aElement: TElement): TStringList;
var
  lSubResult: TStrings;
begin
  Result := TStringList.Create;
  try
    if Assigned( aElement )
    then
      begin
        lSubResults := Traversiere( aElement.gibSohn( ToLinks ) );
        try
          Result.AddStrings( lSubResults );
        finally
          lSubResults.Free;
        end;

        if aElement <> Wurzel
        then
          Result.Add( aElement.gibInhalt );

        lSubResults := Traversiere( aElement.gibSohn( ToRechts ) );
        try
          Result.AddStrings( lSubResults );
        finally
          lSubResults.Free;
        end;
     end;
  except
    Result.Free;
    raise;
  end;
end;

mucki64 29. Apr 2016 20:49

AW: Liste von Arrays
 
Ja, es lohnt sich wirklich, den Speicher nicht für eine neue Instanz Inhalt pro Aufzuf verschwenden, danke für die guten Vorschläge.
Mein Hauptproblem aber bleibt: Inhalt.Add() akzeptiert nur einen String, aber keine TStringList. Somit läßt sich meine Methode gar nicht kompilieren.

Sir Rufo 29. Apr 2016 22:32

AW: Liste von Arrays
 
Zitat:

Zitat von mucki64 (Beitrag 1337157)
Ja, es lohnt sich wirklich, den Speicher nicht für eine neue Instanz Inhalt pro Aufzuf verschwenden, danke für die guten Vorschläge.
Mein Hauptproblem aber bleibt: Inhalt.Add() akzeptiert nur einen String, aber keine TStringList. Somit läßt sich meine Methode gar nicht kompilieren.

Warum habe ich wohl Delphi-Referenz durchsuchenTStrings.AddStrings verwendet? :roll:

mucki64 30. Apr 2016 10:20

AW: Liste von Arrays
 
Danke, das habe ich übersehen. Deine Lösung leistet das Gewünschte.:-D

jfheins 30. Apr 2016 21:09

AW: Liste von Arrays
 
Zitat:

Zitat von Sir Rufo (Beitrag 1337149)
Eine Möglichkeit (garantiert ohne MemLeaks) wäre
*snip*

Aber das ist ja auch suboptimal. Da wird ja für jeden Knoten eine neue Stringlist erstellt, und dann steigen die Add-Aufrufe mit der Knotenanzahl stark (quadratisch?) an...

Besser wäre es imho, die StringListe als Parameter zu übergeben. Der Aufrufer muss da vorher ein gültiges Objekt hineinstecken und hat konsequenterweise danach die Aufgabe, dasselbe aufzuräumen.
In etwa so:
Delphi-Quellcode:
function TBaum.Traversiere( aElement: TElement, const InhaltsListe: TStringList) : TStringList;
begin
   if Assigned(aElement) then
   begin
      Traversiere(aElement.gibSohn(ToLinks), InhaltsListe));

      if aElement <> Wurzel then // Warum eigentlich das hier??
        InhaltsListe.Add(aElement.gibInhalt);

      Traversiere(aElement.gibSohn(ToRechts), InhaltsListe);
   end;
   Result := InhaltsListe
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:41 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