2010-04-16 14 views
5

Mam listę obiektów znajdujących się obok siebie (wiersze załadowane z bazy danych SQL z kluczem i jego kluczem nadrzędnym), których potrzebuję do zbudowania nieuporządkowanego drzewa. Gwarantuje to, że nie ma cykli.Najbardziej efektywny sposób tworzenia drzewa z listy sąsiedztwa

Trwa to zbyt długo (przetwarzane tylko ~ 3K z 870K węzłów w około 5 minut). Działa na mojej stacji roboczej Core 2 Duo z dużą ilością pamięci RAM.

Jakieś pomysły, jak przyspieszyć działanie?

public class StampHierarchy { 
    private StampNode _root; 
    private SortedList<int, StampNode> _keyNodeIndex; 

    // takes a list of nodes and builds a tree 
    // starting at _root 
    private void BuildHierarchy(List<StampNode> nodes) 
    { 
     Stack<StampNode> processor = new Stack<StampNode>(); 
     _keyNodeIndex = new SortedList<int, StampNode>(nodes.Count); 

     // find the root 
     _root = nodes.Find(n => n.Parent == 0); 

     // find children... 
     processor.Push(_root); 
     while (processor.Count != 0) 
     { 
      StampNode current = processor.Pop(); 

      // keep a direct link to the node via the key 
      _keyNodeIndex.Add(current.Key, current); 

      // add children 
      current.Children.AddRange(nodes.Where(n => n.Parent == current.Key)); 

      // queue the children 
      foreach (StampNode child in current.Children) 
      { 
       processor.Push(child); 
       nodes.Remove(child); // thought this might help the Where above 
      } 
     } 
    } 
} 

    public class StampNode { 
     // properties: int Key, int Parent, string Name, List<StampNode> Children 
    } 
+0

Czy naprawdę musisz to zrobić w języku C#? Ponieważ będzie dużo szybciej zamówić węzły według ścieżki w SQL, dzięki czemu można zbudować drzewo w czasie O (N). – Aaronaught

+0

Jak mogę zamówić przez ścieżkę w SQL? Moje dane są jak wykres org ... wiele dzieci i mnóstwo nierównych poziomów. –

Odpowiedz

3
  1. Put węzły do ​​posortowanej listy lub słownika.

  2. Zeskanuj tę listę, podnieś każdy węzeł, znajdź jego węzeł nadrzędny na tej samej liście (wyszukiwanie binarne lub wyszukiwanie w słowniku), dodaj go do kolekcji Dzieci węzła nadrzędnego.

Nie ma potrzeby, aby stos umieszczał go w drzewie.

+0

Warto zauważyć, że sortowanie węzłów według klucza przed umieszczeniem ich na posortowanej liście powoduje ogromną różnicę w szybkości. Idź ze słownikiem to kolejna alternatywa, jeśli pamięć nie jest podstawowym ograniczeniem. – Codism

1

SortedList nie jest dobrym kontenerem do użycia w tym kontekście. Jest to O (n) dla operacji wstawiania (powtarzające się wywołania Add()), ponieważ jest wewnętrznie reprezentowane jako lista pusta. Używanie Dictionary zamiast SortedList będzie dużym usprawnieniem, ponieważ jest to O (1) czas amortyzacji.

+0

Ah, również przegapiłem linię current.Children.AddRange. Nie chcesz ponownie skanować całej listy węzłów, szukając każdego z rodziców. Jak zasugerował Hightechrider, umieszczenie węzłów w Słowniku przyspieszyłoby znacznie, ponieważ ponownie zmienisz operację O (n) na operację O (1). –

Powiązane problemy