2010-03-10 7 views
2

Je dépend de VirtualTreeView pour afficher des milliers d'éléments qui sont susceptibles de changer de temps en temps et lorsque cela se produit l'arbre est nettoyé et peuplé à nouveau.VirtualTreeview: quand trier les enfants?

Le tri est fait automatiquement (toAutoSort flag set) mais cela a un effet indésirable d'initialiser récursivement tous les nœuds et c'est une opération très coûteuse comme vous pouvez l'imaginer.

Alors, quand dois-je appeler la méthode .Sort lorsque toAutoSort est désactivée? (DoInitChildren semblait plausible mais j'ai obtenu des résultats bizarres comme des résultats inversés occasionnellement, donc je suppose que ce n'est pas un bon événement pour trier les enfants.)

Répondre

4

La règle générale dans ce genre de scénario est de trier après que tous les nouveaux éléments ont été ajoutés. De cette façon, vous ne faites que trier (et initialiser) une fois.

+0

Il n'y a pas de "nouveaux" articles à proprement parler. L'arbre est simplement réorganisé et reconstruit (car les structures de données supportant l'arbre changent complètement dans mon cas). –

+1

"Reconstruire" l'arbre équivaut à en créer un nouveau. Le principe est le même: suspendre le tri, commencer la construction, ajouter tous les nœuds, terminer la construction, puis trier. –

1

À moins que l'arborescence entière ne soit complètement différente à chaque fois, vous pouvez obtenir de meilleures performances en ne supprimant pas l'arborescence, mais en créant séparément une nouvelle liste d'éléments (identification des éléments), en triant les arbres pour ... l'algorithme général ressemble à ceci (la liste de gauche est la « nouvelle liste » et la liste de droite est la « liste existante »):

LeftCur := 0; 
RightCur := 0; 
while (LeftCur < TotalLeft) and (RightCur < TotalRight) then 
    begin 
    if LeftList[LeftCur] = RightList[RightCur] then 
     begin 
     // matches, so just advance 
     Inc(LeftCur); 
     Inc(RightCur);    
     end 
    else if LeftList[LeftCur] < RightList[RightCur] then 
     begin 
     // insert happens BEFORE RightCur 
     InsertLeftItemToRight; 
     Inc(RightCur); 
     Inc(TotalRight); 
     end 
    else if LeftList[LeftCur] > RightList[RightCur] then 
     begin 
     DeleteRightItem; 
     Dec(TotalRight); 
     end; 
    end; 
    While RightCur < TotalRight do 
    begin 
     DeleteRightItem; 
     Dec(TotalRight); 
    end; 
    While LeftCur < TotalLeft do 
    AppendLeftItemToRight; 

de cette façon, la liste reste triée, et vous Il suffit de terminer le chargement d'un élément dans les étapes InsertLeftItemToRight. Dans un arbre, chaque fois que vous faites correspondre, vous exécutez une routine similaire pour les enfants. Ce concept est pondéré par le fait que les éléments de la liste existante ne vont pas beaucoup changer ou peuvent être coûteux à charger complètement.

+0

Merci pour la réponse détaillée, mais VirtualTreeView est si flamboyant rapide, simple tactique Effacer/recharger semble assez. (apparemment sauf le tri si :) –