【问题标题】:Most efficient way of creating tree from adjacency list从邻接表创建树的最有效方法
【发布时间】:2011-02-08 22:10:06
【问题描述】:

我有一个需要用来构建无序树的对象的邻接列表(从 SQL 数据库加载的行,带有键和它的父键)。保证没有循环。

这花费的时间太长(大约 5 分钟内处理了 870K 节点中的约 3K)。在具有大量 RAM 的工作站 Core 2 Duo 上运行。

关于如何使这更快的任何想法?

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
    }

【问题讨论】:

  • 您是否必须在 C# 中执行此操作?因为在 SQL 中按路径对节点进行排序会快得多,然后您可以在 O(N) 时间内构建一棵树。
  • 如何在 SQL 中按路径排序?我的数据就像一个组织结构图......很多孩子和很多参差不齐的级别。

标签: c# algorithm adjacency-list


【解决方案1】:
  1. 将节点放入排序列表或字典中。

  2. 扫描该列表,取出每个节点,在同一个列表中找到其父节点(二分查找或字典查找),将其添加到父节点的 Children 集合中。

不需要堆栈将其放入树中。

【讨论】:

  • 值得注意的是,在将节点放入排序列表之前按键对节点进行排序会在速度上产生巨大差异。如果内存不是主要约束,使用字典也是另一种选择。
【解决方案2】:

SortedList 不是在这种情况下使用的好容器。插入操作(对 Add() 的重复调用)是 O(n),因为它在内部表示为平面列表。使用 Dictionary 而不是 SortedList 将是一个很大的改进,因为它是 O(1) 摊销插入时间。

【讨论】:

  • 啊,我也错过了 current.Children.AddRange 行。您不想重新扫描整个节点列表以搜索每个父节点。正如 Hightechrider 建议的那样,首先将节点放入 Dictionary 会大大加快速度,同样,您将 O(n) 操作更改为 O(1) 操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-23
  • 1970-01-01
  • 2010-11-16
  • 1970-01-01
  • 2022-01-17
相关资源
最近更新 更多