Also habe ich mich damit beschäftigt, meine eigene Datenstruktur zu erstellen. Ich habe es schließlich funktionierte, aber dann entdeckte ich, dass die Speichernutzung im Vergleich zu der alten Methode lächerlich hoch war.
Um dies zu testen, habe ich die gleiche Test-App erstellt, aber ich würde die Daten in meinen PVirtualNodes speichern.
Beim Hinzufügen von 1000 Roots mit jeweils 1000 Children verwendete die separate Datenstruktur ungefähr 208 MB, während der PVirtualNode nur ungefähr 160 MB verwendete, und es war auch ein kleines bisschen schneller.
Ich dachte, eine separate Datenstruktur sollte weniger Speicher verbrauchen und schneller sein, aber ich nehme an, dass das der Preis ist?
Hier ist die Quelle für die "Daten in PVirtualNode speichern": Ссылка
Hier ist die Quelle für die "Daten in separater Datenstruktur speichern": Ссылка
Das erste Problem, das ich bei Ihrem separaten Datenstrukturcode sehe, ist, dass die Kategorie die Benutzer fälschlicherweise enthält. Das heißt, wenn dieselbe physische Person in zwei Kategorien unterteilt ist, erscheint sie in Ihrer Datenstruktur so, als ob es zwei völlig getrennte Personen gäbe. Sie werden die Lebensdauer des Projekts damit verbringen, diese Entscheidung zu bedauern.
Sie benötigen eine Liste von Benutzern, und Sie benötigen eine Liste von Kategorien. Ein Benutzer kann eine Liste von Kategorien enthalten, zu denen er gehört, oder eine Kategorie kann eine Liste von Benutzern enthalten, die zu ihr gehören. Vielleicht beides.
%Vor%Beachten Sie, wie dieser Code die Baumkontrolle nicht erwähnt. Eine Kontaktliste besitzt kein Baum-Steuerelement. Wenn dies der Fall wäre, wären Sie wieder da, wo Sie vor Monaten angefangen haben, wo Sie das Problem hatten, wie Benutzer in mehreren Baumstrukturen angezeigt werden. Kontrollen . Beachten Sie auch, dass ein Benutzer in mehr als einer Kategorie angezeigt werden kann, aber keine einzelne Kategorie diesen Benutzer besitzt. Stattdessen besitzt die Kontaktliste den Benutzer und gewährt Kategorien die Berechtigung, auf sie zu verweisen und umgekehrt.
Eines Ihrer ersten Probleme beim Start dieses Projekts war , wie Sie doppelte Elemente im Tree Control erkennen können . Jetzt ist dieses Problem viel einfacher, weil es überhaupt keine Baumkontrolle gibt. Sie müssen nur Duplikate in der flachen Benutzerliste finden. Wenn Sie der Liste zunächst keine Duplikate hinzufügen, müssen Sie sich keine Gedanken darüber machen, ob Sie in einer komplizierteren GUI-Steuerung Duplikate finden.
Beachten Sie, dass die Datenstruktur kein Baum ist. Es sind zwei Listen, und jedes Element in der Liste kann sich auf eine beliebige Anzahl von Elementen aus der gegenüberliegenden Liste beziehen. In diesem Sinne ist es eigentlich ein Graph . Sie zeigen die Daten nur als Baum an, weil sie sonst schwer zu visualisieren sind.
Nun, da Sie eine Datenstruktur haben, die unabhängig von den Tree-Controls ist, wie verbinden Sie den Tree mit den Daten, die er anzeigen soll? Jeder Knoten sollte einen Verweis auf die von ihm repräsentierte TUser
oder TCategory
enthalten. Der Datensatz des Knotens könnte wie folgt definiert werden:
Sie können damit das OnGetText
-Ereignis des Baums wie folgt implementieren:
Das heißt, jeder Knoten enthält entweder einen Benutzer oder eine Kategorie. Das erste Element des Arrays enthält einen Wert, der einem dieser Typen entspricht. Da Sie jedoch nicht im Voraus wissen, was es sein wird, haben Sie einen dritten Typ, der sicher als eines verwendet werden kann: TObject
. Es ist wichtig, die erforderlichen Daten im ersten Feld des Datensatzes zu haben, da dies das Feld ist, das Sie beim Aufruf von AddNewNode
festlegen dürfen, auch bevor der Knoten vollständig initialisiert wurde.
Eines der Geheimnisse zur Vermeidung von langen Node-Erstellungszeiten besteht darin, das Erstellen der Knoten zu vermeiden, die Sie nicht benötigen. Wenn ein Knoten der obersten Ebene minimiert ist, müssen Sie keine untergeordneten Knoten erstellen. Setzen Sie einfach das Flag auf den obersten Knoten, um anzuzeigen, dass untergeordnete Elemente ist, und es wird sich korrekt mit der Schaltfläche "+" darstellen. Wenn der Benutzer später auf die Schaltfläche klickt, um den Knoten zu erweitern, fragt das Struktursteuerelement, wie viele untergeordnete Elemente es hat und an welcher Stelle es erstellt wird. Und selbst dann initialisiert die Knoten, die sofort gemalt werden müssen. Verzögern Sie die Arbeit, bis es notwendig ist. Jemand mit einer Million Kontakten wird wahrscheinlich nie alle gleichzeitig sehen wollen. Es besteht also keine Notwendigkeit, eine Million Elemente in der GUI-Steuerung zu erstellen.
Wenn das Programm gestartet wird, müssen Sie zuerst die Benutzer- und Kategorielisten laden und dann die Kategorienanzahl der Struktur festlegen:
%Vor%Das ist alles.
Das Ereignis des Baums wird den Rest der Initialisierungsphase übernehmen. Wenn Sie möchten, dass einige der Kategorieknoten von Anfang an erweitert werden, müssen Sie sie nur erweitern. Die Ereignisse des Baums werden Sie fragen, wie viele Kinder jeder Knoten hat, und Sie können das Ereignis implementieren, um zu antworten. Sobald der Baum Knoten für sie erstellt hat, wird gefragt, wie sie initialisiert werden sollen, und Sie können dem Knoten zu diesem Zeitpunkt das entsprechende Benutzer- oder Kategorieobjekt zuweisen. Der Baum wird Ihnen sagen, wenn es mehr Informationen benötigt. Sie müssen es nicht mehr geben, als es verlangt.
Tags und Links delphi data-structures memory-management virtualtreeview