| Autor |
Beitrag |
jawo3
Hält's aus hier
Beiträge: 10
|
Verfasst: So 20.02.11 21:36
Hi,
ich habe eine Programm, dass nach Eingabe von Werten grafisch einen Binärbaum ausgibt, was soweit auch wunderbar funktioniert.
Jetzt soll dies um eine Funktion erweitert werden, die nach Klick auf einen Button den Baum durchfährt und bei Bedarf entsprechende Rotationen ausführt.
Die Knoten sind so aufgebaut:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| type Zeiger = ^Knoten; tInhalt = string[1]; Knoten = record links: Zeiger; rechts: Zeiger; Inhalt: tInhalt; balance: integer; end; |
Die Funktion soll der Einfachheit halber erstmal nur einfache Rotation nach links erlauben. Hier mein Versuch:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure TForm1.ButtonBalancierenClick(Sender: TObject); var zw,zw2: Zeiger; procedure Balancieren(var z: Zeiger); begin if z<> nil then begin Balancieren(z^.links); if z^.balance>1 then begin zw:=z; zw2:=z^.rechts; z:=zw2; z^.links:=zw; end end; end; begin Balancieren(wurzel); ausgeben(wurzel); end; |
Dies funktioniert allerdings nicht. Es scheint irgendeinen logischen Fehler in meiner Balance-Prozedur zu geben.
Vielleicht könnt ihr mir einen kleinen Denkanstoß geben.
Vielen Dank im Voraus
jawo3
PS: Im Anhang mal ein Bild von der beabsichtigten Funktion.
Einloggen, um Attachments anzusehen!
|
|
Xion
      

Beiträge: 1952
Erhaltene Danke: 128
Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
|
Verfasst: Mo 21.02.11 11:26
_________________ a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
|
|
jawo3 
Hält's aus hier
Beiträge: 10
|
Verfasst: Mo 21.02.11 23:06
Danke erstmal für die Antwort!
Ich habe jetzt einen ersten Lösungsansatz, der bei einmaligem Ausführen auch ohne Fehler für den von Xion oben angegebenen Fall funktioniert.
Allerdings sieht das ziemlich schlecht aus
Ich hoffe ihr könnt mir helfen, dass ein bisschen besser zu schreiben.
Ich habe auch noch nicht ganz verstanden, warum ich Fehler in der Grafik-Zeichnen-Prozedur erhalte, wenn ich nicht mit new() in der Balance-Prozedur die Zeiger zum Zwischenspeichern bekanntgebe und für alle Record-Elemente Werte vergebe.
Hier also mein Quelltext / ich hoffe ihr könnt mir damit helfen:
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:
| procedure TForm1.ButtonBalancierenClick(Sender: TObject); var zw,zw2,zw3: Zeiger; procedure Balancieren(var z: Zeiger); begin new(zw); zw^.rechts:=nil; zw^.links:=nil; zw^.balance:=0; new(zw2); zw2^.rechts:=nil; zw2^.links:=nil; zw2^.balance:=0; new(zw3); zw3^.rechts:=nil; zw3^.links:=nil; zw3^.balance:=0;
zw:=z^.links; zw2^.inhalt:=z^.inhalt; z:=zw; zw3^.inhalt:=zw2^.inhalt; z^.rechts:=zw3; end; begin Balancieren(wurzel); GrafikSteuerung(); end; |
Vielen Dank im Voraus
jawo3
|
|
Xion
      

Beiträge: 1952
Erhaltene Danke: 128
Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
|
Verfasst: Di 22.02.11 00:34
_________________ a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
|
|
jawo3 
Hält's aus hier
Beiträge: 10
|
Verfasst: Di 22.02.11 01:03
Danke, ich habs mal so ausprobiert.
Allerdings bleibt dann nach Eingabe der Werte "C,B,A" nur noch der Wert C übrig.
Die anderen tauchen gar nicht mehr auf 
|
|
Xion
      

Beiträge: 1952
Erhaltene Danke: 128
Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
|
Verfasst: Di 22.02.11 10:30
Ja, ans Ende muss noch
Result:=y; Musst du nur noch deine procedure mit dem Var-Parameter in eine Funktion umbauen
Oder du probierst mal
z:=y; am Ende...das müsste auch gehen durch den var-Parameter
_________________ a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
|
|
jawo3 
Hält's aus hier
Beiträge: 10
|
Verfasst: Di 22.02.11 15:14
Super, das scheint zu funktionieren
Falls es noch Probleme geben sollte, melde ich mich nochmal.
Vielen Dank
jawo3
|
|
jawo3 
Hält's aus hier
Beiträge: 10
|
Verfasst: So 27.02.11 01:15
Soooo...
Ich habe heute versucht, eine Doppelrotation-Funktion einzubauen, da der Baum bisher ja nicht optimal ausbalanciert werden kann. Wenn ich zum Beispiel: "D,A,C" eingebe, schafft die bisherige Prozedur keine gescheite Balancierung.
Wenn ich das richtig verstanden habe, setzt die Doppelrotation immer dann ein, wenn das Folgeelement des betroffenen Elements mit zu hohem oder zu niedrigem Balancewert eine genau gegensätzliche Balancestufe hat z.B. Wurzel hat zu viel links und das linke Folgeelement hat zu viel rechts.
Also habe ich eine Abfrage eingebaut, die genau dies testet und dann entsprechend zwei verschiedene Rotationen ausführt.
Lasse ich das Programm mit folgendem Quelltext laufen, erhalte ich allerdings immer die Fehlermeldung "EAccessViolation", wenn ich die Balance-Prozedur aufrufe.
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:
| procedure TForm1.ButtonBalancierenClick(Sender: TObject); var y,x: Zeiger; procedure Balancieren(var z: Zeiger); begin if z<>nil then begin Balancieren(z^.links); if z^.balance<-1 then begin y:=z^.links; if y^.balance>0 then begin x:=y; y^.Balance:=y^.Balance-2; x^.Balance:=x^.Balance-1; y^.rechts:=x^.links; x^.links:=y; y:=x; end else begin z^.Balance:=z^.Balance+2; y^.Balance:=y^.Balance+1; z^.links:=y^.rechts; y^.rechts:=z; z:=y; end; end; end else if z^.balance>1 then begin y:=z^.rechts; if y^.balance<0 then begin x:=y; y^.Balance:=y^.Balance+2; x^.Balance:=x^.Balance+1; y^.links:=x^.rechts; x^.rechts:=y; y:=x; end else begin z^.Balance:=z^.Balance-2; y^.Balance:=y^.Balance-1; z^.rechts:=y^.links; y^.links:=z; z:=y; end; end; Balancieren(z^.rechts); end; begin Balancieren(wurzel); Balance_Test(wurzel); GrafikSteuerung(); end; |
Vielleicht könnt ihr mir nochmal einen kleinen Denkanstoß geben, das wäre super!
Vielen Dank im Voraus
jawo3
|
|
Xion
      

Beiträge: 1952
Erhaltene Danke: 128
Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
|
Verfasst: So 27.02.11 09:48
Ja...das ist ne knifflige Sache, das hat bei mir auch nicht so ganz gestimmt.
www.tu-ilmenau.de/fa...-Kap-4-blaettern.pdf
Guck mal da. Du musst da relativ viele Ausnahmen bedenken.
_________________ a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: So 27.02.11 10:53
Hallo,
es gab im Forum schon mal die Anfrage AVl-Baum:
www.delphi-forum.de/...mp;highlight=avlbaum
der Link auf Borland's Version ist nun auf
www.efg2.com/Lab/Lib...seNet/2000/0315c.txt
gelandet.Ich habe es mal komprimiert angehängt.
Da hat man direkt zu begin die rotate Befehle implementiert und sieht die diversen Bedingungen, die beim Umhängen der Knoten beachtet werden müssen.
Du kannst ja Kommentare dazu schreiben, was in jeder Zeile passiert, indem Du es aufzeichnest oder in der obengenannten PDF ab Seite 357 dies Schritt für Schritt verfolgst.
Gruß Horst
Einloggen, um Attachments anzusehen!
|
|
elundril
      
Beiträge: 3747
Erhaltene Danke: 123
Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
|
Verfasst: So 27.02.11 17:28
Darf ich fragen warum ihr eigentlich noch immer hier mit Pointern durch die Gegend schießt? Wären Referenzen nicht wesentlich sinnvoller bzw einfacher?
lg elundril
_________________ This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
|
|
jawo3 
Hält's aus hier
Beiträge: 10
|
Verfasst: Di 01.03.11 13:49
Danke für eure Hilfe!
Ich denke mittlerweile, das mir das zu komplex ist, deshalb belasse ich es erstmal bei der einfachen Rotierung
@elundril
Zeiger waren eine Vorgabe...
|
|
|