Наиболее эффективный способ создания дерева из списка смежности

#algorithm #matrix #tree #adjacency-matrix

Вопрос:

У меня есть список объектов смежности (строки, загруженные из базы данных SQL с ключом, и это родительский ключ), который мне нужно использовать для построения неупорядоченного дерева. У него гарантированно не будет циклов.

Это занимает слишком много времени (обрабатывается только ~3 тыс. узлов из 870 тыс. примерно за 5 минут). Работает на моей рабочей станции Core 2 Duo с большим количеством оперативной памяти.

Есть какие-нибудь идеи о том, как сделать это быстрее?

 public class StampHierarchy {  private StampNode _root;  private SortedListlt;int, StampNodegt; _keyNodeIndex;   // takes a list of nodes and builds a tree  // starting at _root  private void BuildHierarchy(Listlt;StampNodegt; nodes)  {  Stacklt;StampNodegt; processor = new Stacklt;StampNodegt;();  _keyNodeIndex = new SortedListlt;int, StampNodegt;(nodes.Count);   // find the root  _root = nodes.Find(n =gt; 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 =gt; 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, Listlt;StampNodegt; Children  }  

Комментарии:

1. Вам обязательно нужно делать это на C#? Потому что будет намного быстрее упорядочить узлы по пути в SQL, с помощью которого вы сможете построить дерево за O(N) время.

2. как я могу упорядочить по пути в SQL? Мои данные похожи на организационную диаграмму… много детей и много неровных уровней.

Ответ №1:

  1. Поместите узлы в отсортированный список или словарь.
  2. Просканируйте этот список, выберите каждый узел, найдите его родительский узел в том же списке (двоичный поиск или поиск по словарю), добавьте его в коллекцию дочерних узлов родительского узла.

Нет необходимости в стеке, чтобы поместить это в дерево.

Комментарии:

1. Стоит отметить, что сортировка узлов по ключу перед помещением их в отсортированный список имеет огромное значение в скорости. Использование словаря также является другой альтернативой, если память не является основным ограничением.

Ответ №2:

SortedList-неподходящий контейнер для использования в этом контексте. Это O(n) для операций вставки (повторные вызовы Add()), так как он внутренне представлен в виде плоского списка. Использование словаря вместо сортированного списка будет большим улучшением, так как это O(1) амортизированное время вставки.

Комментарии:

1. Ах, еще я соскучился по течению. Дети. Добавить строку. Вы не хотите повторно сканировать весь список узлов в поисках каждого родителя. Как и предполагал Хайтехрайдер, ввод узлов в словарь сначала значительно ускорит процесс, поскольку, опять же, вы измените операцию O(n) на операцию O(1).