Autor Beitrag
O'rallY
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 563



BeitragVerfasst: So 13.04.03 14:42 
Wie kann ich in Delphi ein solches Baumdiagramm zeichnen?
user defined image
Ich will das Heapsort-Verfahren grafisch darstellen, nur schaffe ich es nicht einen einfachen Baum zu zeichnen... Ich bitte um Tipps, links, usw.

_________________
.oO'rallY
Linux is like a tipi: No gates, no windows and a gnu-eating apache inside...
O'rallY Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 563



BeitragVerfasst: So 13.04.03 15:50 
Natürlich stelle ich mir dieses Diagramm sehr stark vereinfacht in einem Canvas vor.

Also ein einfaches Baumdiagramm mit Kreisen und Linien, nicht mehr und nicht weniger.

_________________
.oO'rallY
Linux is like a tipi: No gates, no windows and a gnu-eating apache inside...
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Mo 14.04.03 10:20 
Hallo,

die Antworten sind hier wohl ein wenig dürftig, weil man da 'ne weile drüber nachdenken muss um zu einer guten lösung zu kommen. Ich muss gestehen, das habe ich auch nicht getahn aber vieleicht kann ich dir ja ein paar Denkanstöße liefern.
Ich denke du solltest dir dein Canvas Rastern, du legts also ein Virtuelles Gitter drüber. Dann überlegst du dir wieviele Gitterfelder ein Knoten benötigt z.B. 3 in der Berite für 1x Kreis + 2x Platz (links&rechts) und 3 in der höhe füe 1x Kreis und 2x Platz unten.
Bevor du Zeichnen kannst, musst du dir funktionen schreiben, die anhand dieser Daten und deine Baumstruktur im Speicher ausrechnen wie groß das Canvas sein muss und es auf die entsprechende Größe setzt. Dann benötigst du eine eben solche, die ausrechnen kann, wo welcher Knoten Positioniert werden muss (denn die Wurzel muss ja nicht immer mittig sitzen je nachdem wie viele Äste in welche richtung gehen).
Das Zeichnen selber wird das geringste Problem sein, wenn du erst einemal diese Mathematischen grundlagen gelegt hast.

Vieleicht kann dir das ja ein wenig helfen.

Gruß
Klabautermann
O'rallY Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 563



BeitragVerfasst: Mi 16.04.03 10:35 
Erstmal danke für die Antwort. Das, wenn ich einmal die mathematischen Grundlagen gelegt habe, das Zeichnen einfach ist, hab ich mir schon gedacht :mrgreen: . Aber bis man die mathematischen Grundlagen gelegt hat, naja, das ist ja auch das Problem :wink: .
Dein Verfahren scheint einleuchten zu sein, doch weiß ich nicht, wie ich es realisieren soll. Wie soll ich das Canvas rastern? Könntest du mir vielleicht diesmal einen Programmiertechnischen anstoß geben :D . Ich habe in diesem Bereich leider noch keinerlei Ehrfahrung (ich arbeite gerade an diesem Defiziet :mrgreen: ). Einen mehrdiminionalen Array zu nehmen erscheint mir irgendwie nicht als eine elegante Lösung....? Da der Array ja bei 10 ebenen schon sehr groß sein muss, da der Baum ja exponentiell wächst. Der Array müsste ja wenigstens 2^10 felder in der Breite haben. Wäre das nicht zu Speicherlastig?

_________________
.oO'rallY
Linux is like a tipi: No gates, no windows and a gnu-eating apache inside...
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Mi 16.04.03 11:33 
Hallo,

von einem Array würde ich auch abraten. Das ist eine Typische aufgabe für Zeigerstrukturen (da lässt sich der beum direcht abbilen, jeder Zeiger ist eine Kante).
Das mit dem Rastern meinte ich so, das du für dich definierst, wie Breit so ein Knoten ist und wie viel Platz du benötigst, um xKnoten nebeneinander darzustellen. Wenn z.B. 3 Knoten nebeneinander dargestellt werden müssen, dann benötigst du ein Breite von 5 Einheiten (Knoten + Frei + Knoten + Frei + Knoten). Den benötigten Breiten Wert musst du für die Breiteste Ebene berechen. Die höhe sollte einfacher zu bestimmen sein.
Irgendwo definierst du dir wie viele Pixel eine Breiteneinheit oder Höheneinheit hat. Diese Kostanten könnte z.B. so aussehen:
ausblenden Quelltext
1:
2:
3:
const
  BreitenEinheit = 25;
  HoehenEinheit = 50;

Wenn du dann die Breite und höhe ermittelst, kannst du damit die benötigte Bildgröße berechnen und selzen (dein Image sollte in eine Scrollbox liegen ;)):
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure SetImageSize;
begin
  Image1.Picture := NIL;
  image1.Width := MaxBreite *  BreitenEinheit;
  image1.Height := Ebenen * HoehenEinheiten;
  image1.Canvas.Rectangle(0, 0, image1.Width, image1.Height);
end;


Gruß
Klabautermann
O'rallY Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 563



BeitragVerfasst: Fr 18.04.03 22:44 
Axo meinst du das *g*.
Meinst du mit Zeigerstruktur eine Liste (hab die genaue Bezeichnung vergessen...heißt es liste? :wink: ) aus Elemente die einen Zeiger besitzen, der aufs nächste Element zeigt?
In meinem Fall hätte jedes Elemet 2 Nachfolger, also besäße es auch 2 Zeiger? Meinst du das so? Wie stellst du dir das Programmiertechnisch vor?
In meinem C/C++ Buch gabs mal ein Beispiel, das Strukturen zu einer Liste verbindand, indem ein zeiger immer auf das nächste Element zeigte. Bei Delphi wären das ja dann records und das wäre wieder ein Speicherproblem... ich muss mir das Beispiel in dem Buch nochmal angucken...
Bin ich auf dem richtige Weg? (deiner Vorstellung nach?)
Fragen über Fragen :D

P.S.: Du bist echt klasse! Ich hoffe du schmeißt mir nicht irgendwann vor Ungeduld die Tastatur an den Kopf :wink:

_________________
.oO'rallY
Linux is like a tipi: No gates, no windows and a gnu-eating apache inside...
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Sa 19.04.03 13:21 
Hallo,

gegenfrage, wie hast du die Daten denn vorliegen?

Bei der Sanche mit den Zeigern hast du mich schon richtig verstanden. WEnn du einen Binären Baum hast kannst du dir das Einfach machen, indem du einen ensprechend eindeutigen Datentyp Sachaffst:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
TYPE
  pData = ^tData;
  tData = packed record
    Cation : String[40];
    Child1, Child2 : pData;
    parent : pData; // Den nur wenn du auch rückwerst durch den Baum laufen willst.
  end; // tData

Die einzelnen Elemente musst du dann zur Laufzeit mit NEW erzeugen und mit DISPOSE wieder Freigeben.
Du solltest also erfahrungen mit Zeigern und natürlich auch mit Rekursionen haben. Notfalls sammele sie ;).
Bäume sind immer Recht datenaufwändig. Mit jeder vollständigen Ebene wird der Speicherverbrauch ben binären Bäumen mehr als verdoppelt. Mit einem Zeiger konstrukt stellst du aber sicher, das nur für Tatsächlich vorhandene Knoten speicher belegt wird bei einer Abbildung z.B. auf ein Array musstest du auch für nichtvorhandene Knoten Felder vorsehen.

Noch ein Tipp: Wenn du mit binären Bäumen arbeitest, kannst du dir die Breitenbestimmung vereinfachen, indem du einfach von der Maximal möglichen Breite ausgehst. Dann wird deine Grafik aber in ungünstigen Fällen recht viel Weißfläche aufweisen (Weil z.B. der Rechte Knoten der Ebene 1 ein Blatt ist, also keine nachfahren mehr hat.

Gruß
Klabautermann