用于将深度数组转换为树的高效算法

时间:2012-08-27 16:58:02

标签: c# algorithm tree

我有一个存储过程,它返回一个在树中组织的名称的平面列表。要传达谁是父亲的深度值,所以5条记录(最多3个级别)的结果如下所示:

Depth|Name
----------
    0|Ford
    1|Compact Cars
    2|Pinto
    1|Trucks
    2|H-Series

我正在尝试通过读取深度值来构造此数组中的树。是否有一些明显的算法来构建这样的数据序列中的树?我正在添加C#标签,因为我对这个问题的LINQy解决方案持开放态度,尽管通用的计算机科学答案会非常有用。

这是我目前的尝试:

class Record
{
  public string Name{ get; set; }
  public List<Record> children { get; set; }
}

var previousLevel = 0;
var records = new List<Record>();

foreach (var thing in TreeFactory.fetch(dao))
{
  if(this.Depth == 0) {
    //Root node
  } else if(thing.Depth > previousLevel) {
    //A Child of the last added node
  } else if(thing.Depth < previousLevel) {
    //A Cousin of the last added node
  } else {
    //A Sibling of the of the last added node
  }
  previousLevel = this.Depth;
}

通过“高效”我说话列表大小高达200,000个元素和树木可以扩展到100个级别,所以我真的只是想找一些更容易推理的东西。

4 个答案:

答案 0 :(得分:3)

这里不需要递归。我相信最快的方法就是:

public static TreeView TreeFromArray(Item[] arr)
{
    var tv = new TreeView();
    var parents = new TreeNodeCollection[arr.Length];
    parents[0] = tv.Nodes;

    foreach (var item in arr)
    {
        parents[item.Depth + 1] = parents[item.Depth].Add(item.Name).Nodes;
    }

    return tv;
}

项目是具有深度和名称信息的任何内容:

public class Item
{
    public int Depth;
    public string Name;
}

当使用我自己的TreeNode实现时,为了简化程序并将其从不需要的功能中剥离,使整个事情变慢,并且稍微改变方法以适应thsoe的变化,我想出了这个:

<强>类:

    public class Node
    {
        public string Name;
        public List<Node> Childs = new List<Node>();
    }

    public class Item
    {
        public int Depth;
        public string Name;
    }

<强>实施

    public static Node TreeFromArray(Item[] arr)
    {
        var tree = new Node();

        var parents = new Node[arr.Length];
        parents[0] = tree;

        foreach (var item in arr)
        {
            var curr = parents[item.Depth + 1] = new Node {Name = item.Name};
            parents[item.Depth].Childs.Add(curr);
        }

        return tree;
    }

<强>结果:

  

使用给定数据:900毫秒内1,000,000次

答案 1 :(得分:1)

public void AddNode(Tree tree, Node nodeToAdd, int depth)
{
  //you might need to add a special case to handle adding the root node
  Node iterator = tree.RootNode;  
  for(int i = 0; i < depth; i++)
  {
    iterator = iterator.GetLastChild(); //I assume this method won't exist, but you'll know what to put here
  }

  iterator.AddChild(nodeToAdd);
}

这有点伪代码。它没有添加错误处理,我假装存在我想象你可以自己解决的代码段的方法。

答案 2 :(得分:1)

此数组看起来像原始树结构的从左到右“展平”。如果可以安全地假设,那么方法很简单:

For each element in the array
   If the depth of the element is less than or equal to the "current node"
      traverse upwards to the parent until current depth = element depth -1
   Create a child node of the current node
   Traverse to that node as the new "current" node

答案 3 :(得分:1)

成分:

  1. 允许子节点的类。
  2. 此类类型的堆栈。
  3. 此类类型的数组或列表。
  4. 存储当前深度的int。
  5. 当地人持有我们当前感兴趣的项目。
  6. 方法

    1. 从列表中取出您的第一个项目。把它放在堆栈中。将0存储为当前深度。
    2. 依次从列表中取出每个剩余的项目。看看它的深度。如果深度等于或小于当前深度,则从堆栈弹出(currentdepth - depth + 1)项目,并在堆栈中查看以获取新的当前项目。使我们的新项目成为“当前项目”的子项,使其成为当前项目,使其深度为当前深度。
    3. 在200°C或Gas-mark 6下用编译器烘烤300毫秒,或直至金黄色。