6 Stimmen

Wie zeichnet man eine Baumstruktur? (Ein zweidimensionaler Raumzuweisungs-Baumrekursionsalgorithmus?)

Ich habe eine beliebige Baumstruktur von Knoten. Ich möchte diesen Baum zeichnen, um den Benutzern eine visuelle Darstellung zu bieten. Ich muss über den Baum rekursieren und für jeden Knoten ein grafisches Element zu einer Liste hinzufügen, und dann einfach die Liste der Elemente zeichnen, sobald die Baumrekursion beendet ist. Die Rekursion und das Zeichnen der Elemente ist natürlich trivial - etwas komplizierter ist es, die Grafikknoten so zu positionieren, dass sie sich nicht mit anderen Zweigen überschneiden.

Ich benutze Android, aber das ist nicht wichtig - ich bin auf der Suche nach einem Ansatz, möglicherweise ein Algorithmus, der ein Bild von 2D-Raum beibehalten kann, wie es über den Baum geht, so dass es nur die am besten geeigneten Koordinaten für jeden Knoten zuweist, wie es den Durchgang macht.

Irgendwelche Ideen?

Update

Dies ist der Artikel mit dem besten und vollständigsten Algorithmus.

4voto

phimuemue Punkte 32518

Ich schlage vor, den Baum in einer Linie zu zeichnen. Dazu verwenden Sie eine Art beweglichen "Zeichencursor".

Sie könnten ein Attribut speichern width für jeden Knoten, die wie folgt berechnet wird:

  • le site width eines Urlaubs ist 1
  • le site width eines inneren Knotens ist die Summe der Werte aller untergeordneten width s

Dann zeichnet man die Wurzel "in der ersten Linie" in der Mitte, d.h. man nimmt einfach die Wurzel des width der Hälfte.

Dann erzeugt man ein Gitter über dem Bild, so dass jede Gitterlinie einer Zeile bzw. einem Schritt von links nach rechts entspricht und jeder Schnittpunkt von Gitterlinien einen Knoten enthalten kann und jeder Knoten genügend Platz hat.

Dann iterieren Sie durch die Kinder, und während der Iteration akkumulieren Sie die Werte der Kinder width s und zeichnen Sie die Kinder "in die nächste Zeile". Zum Zeichnen currentChild bewegen Sie Ihren Zeichencursor currentWidth/2 nach rechts, zeichnen currentChild und bewegen Sie den Zeichencursor um die restlichen currentWidth/2 nach rechts.

Um die Knoten in eine gute Reihenfolge zu bringen, könnten Sie eine Suche in der Breite in Betracht ziehen.

Ich hoffe, meine Erklärung ist klar, aber ich denke, es wird besser sein, wenn ich ein kleines Bild zeichne.

Dies ist unser Baum ( x sind Knoten, alles andere sind Kanten)

   +-------x--+-------+
   |          |       |
 +-x-+     +-+x+-+  +-x-+
 |   |     | | | |  | | |
 x   x     x x x x  x x x

Sie berechnen also den Wert des Blattes width s:

   +-------x--+-------+
   |          |       |
 +-x-+     +-+x+-+  +-x-+
 |   |     | | | |  | | |
 1   1     1 1 1 1  1 1 1

Dann, von unten nach oben, die width s als Summen der Kinder width s:

   +-------9--+-------+
   |          |       |
 +-2-+     +-+4+-+  +-3-+
 |   |     | | | |  | | |
 1   1     1 1 1 1  1 1 1

Sie beginnen also an der Wurzel ( width 9) und gehen Sie 4,5 Schritte zur rechten Seite in der ersten Zeile.

Dann bewegen Sie Ihren "Zeichencursor" auf die zweite Zeile, "Spalte 0" (nach links).

Das erste Kind hat width 2, also gehen wir 2/2=1 Gitterlinien nach rechts, zeichnen Sie den Knoten und bewegen Sie den Zeichencursor die verbleibenden 1 Gitterlinien nach rechts, um den Knoten fertigzustellen. Der nächste Knoten hat also width 4, was bedeutet, dass wir 4/2=2 Gitterlinien nach rechts gehen, zeichnen, die restlichen 2 Schritte gehen, und so weiter.

Und so geht es weiter mit der nächsten Zeile. Verbinden Sie am Ende (oder in Zwischenschritten) die Knotenpunkte.

Dieses Verfahren stellt sicher, dass es keine sich überschneidenden Knoten gibt (wenn die Gitterlinien weit genug voneinander entfernt sind), aber es kann zu recht großen Baumdiagrammen führen, die den Platz effizienter nutzen könnten.

Um ungenutzten Raum zu erkennen, könnte man die Linien nach dem obigen Vorgang einfach scannen und nachsehen, ob es ungenutzte Gitterlinienkreuzungen gibt, und dann möglicherweise einige Knoten neu ausrichten, um den Raum zu füllen.

4voto

Jay Askren Punkte 10053

Ich würde den Walker-Algorithmus ausprobieren. Hier ist ein akademischer Artikel über den Algorithmus. Wenn Sie sich den Code ansehen möchten, sehen Sie sich die NodeLinkTreeLayout en Prefuse . Prefuse ist quelloffen, so dass es keine Probleme geben sollte, den Code an Ihre Situation anzupassen, solange Sie die Bedingungen der Lizenz befolgen.

2voto

pmod Punkte 9810

Werfen Sie einen Blick auf Punkt . Sie können Ihren Baum in die Punktdarstellung konvertieren und dann mit Graphviz in jedem beliebigen Format visualisieren. Zum Beispiel Doxygen verwendet es, um die Struktur des Programms darzustellen.

2voto

LarsH Punkte 26458

Graphviz und mfgraph sind sehr leistungsfähig, aber sie sind für allgemeine Graphen gedacht und für Bäume wahrscheinlich überflüssig.

Googeln Sie mal nach Baum+Layout+Algorithmus oder sehen Sie nach Grafik Javascript Baum mit Layout . Letztere ist alt, aber sie verwendet HTML-Canvas und Javascript, und sie erklärt den Code, so dass sowohl der Code als auch der Ansatz portabel sein sollten.

0voto

Carl Manaster Punkte 38966

Je nach Art Ihrer Daten kann ein TreeMap ist vielleicht besser geeignet als eine Bastelvorlage.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X