Autor Beitrag
Pepp3r
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 82



BeitragVerfasst: So 13.03.11 17:57 
Hallo ihr lieben,
habe ein kleines Problem und ich weiß nicht worauf es zurück zu führen ist. Ich möchte einen Suchbaum programmieren. Ich weiß wie ein solcher funktioniert und wie ich ihn programmieren kann. Leider erhalte ich beim einfügen der der Knoten einen Laufzeiterror bezühglich der Speicheradressen. Meine function übergibt anscheinend nicht die richtige Speicheradresse. Hier der Quelltext:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type

  Knoten = ^TKnoten;

  TKnoten = record
    wert: String;
    links,
    rechts: Knoten;
  end;

  TSuchbaum = class
    private
      wurzel: Knoten;
      constructor create;
      procedure wurzelSetzen(wert: String);
      function blattFinden(wert: String; verglKnoten: Knoten): Knoten;
      procedure einfuegen(wert: String; blatt: Knoten);
    public
  end;

  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  Suchbaum: TSuchbaum;

implementation

{$R *.dfm}

constructor TSuchbaum.create;
begin
  wurzel := nil;
end;

procedure TSuchbaum.wurzelSetzen(wert: String);
begin
  //Wurzel als isolierter Knoten
  wurzel := new(Knoten);
  wurzel.wert := wert;
  wurzel.links := nil;
  wurzel.rechts := nil;
end;

function TSuchbaum.blattFinden(wert: String; verglKnoten: Knoten): Knoten;
begin
  if wert < verglKnoten.wert then
  begin
  if verglKnoten.links = nil then
    result := verglKnoten
  else
    blattFinden(wert, verglKnoten.links) //links weiter suchen
  end
  else
  if wert >= verglKnoten.wert then
  begin
  if verglKnoten.rechts = nil then
    result := verglKnoten
  else
    blattFinden(wert, verglKnoten.rechts);  //rechta weiter suchen
  end
end;

procedure TSuchbaum.einfuegen(wert: String; blatt: Knoten);
begin
  if wert < blatt.wert then  {<---hier kommt die falsche Adresse an, beispielsweise bei der eingabe {b, f, a, c}}
  begin
    blatt.links := new(Knoten);
    blatt.links.links := nil;
    blatt.links.rechts := nil;
    blatt.links.wert := wert;
  end
  else
  if wert >= blatt.wert then
  begin
    blatt.rechts := new(Knoten);
    blatt.rechts.links := nil;
    blatt.rechts.rechts := nil;
    blatt.rechts.wert := wert;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Suchbaum := TSuchbaum.create;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if Suchbaum.wurzel = nil then
    Suchbaum.wurzelSetzen(Edit1.Text)
  else
    Suchbaum.einfuegen(Edit1.Text, Suchbaum.blattFinden(Edit1.Text, Suchbaum.wurzel)); 
end;

end.


Wo könnte der Fehler liegen?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19336
Erhaltene Danke: 1751

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 13.03.11 18:03 
user profile iconPepp3r hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
type

  Knoten = ^TKnoten;
Die Bezeichnung ist irreführend. Dass Typen mit einem großen T anfangen, weißt du ja schon, aber Pointertypen fangen entsprechend mit P an. Du solltest den Typ also PKnoten nennen. ;-)

Denn sonst denkt man bei Knoten eher, dass das eine Variable ist.

user profile iconPepp3r hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
function TSuchbaum.blattFinden(wert: String; verglKnoten: Knoten): Knoten;
begin
  if wert < verglKnoten.wert then
  begin
  if verglKnoten.links = nil then
    result := verglKnoten
  else
    blattFinden(wert, verglKnoten.links) //links weiter suchen
  end
  else
  if wert >= verglKnoten.wert then
  begin
  if verglKnoten.rechts = nil then
    result := verglKnoten
  else
    blattFinden(wert, verglKnoten.rechts);  //rechta weiter suchen
  end
end;
Du solltest beim rekursiven Aufruf den gefundenen Wert auch zurückgeben. Warnt Delphi dich nicht zufällig, dass der Rückgabewert undefiniert sein könnte? :zwinker:

Zudem hast du vergessen die Records auch wieder mit Dispose irgendwo freizugeben. Du hast also ein Speicherleck, da du immer nur Speicher mit New reservierst.
Pepp3r Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 82



BeitragVerfasst: So 13.03.11 18:08 
Jau das wars. Manchmal sieht man den Baum vor lauter Wald nicht mehr. Hätte ich jetzt noch stunden dran gehangen, danke für die erlösung :P
edit:// danke auch für die Tips zur Formalität!
Gruß
Pepp3r
Pepp3r Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 82



BeitragVerfasst: So 13.03.11 18:17 
Zitat:

Zudem hast du vergessen die Records auch wieder mit Dispose irgendwo freizugeben. Du hast also ein Speicherleck, da du immer nur Speicher mit New reservierst.


Ja das ist mir schon klar, war noch nicht so weit. Schon ungewohnt ohne Garbagecollector wenn man jahre zuvor mit Java gelernt hat :P