如何在没有递归的情况下遍历这个树结构c#

时间:2017-01-15 00:41:08

标签: c# performance tree recursive-datastructures

这段代码将循环数据保存在数据库中,但是我遇到了性能问题,因为数据太大了,它可以节省大量的记录,在这种情况下,递归会给内存带来非常大的负载,所以我需要一个替代解决方案来知道递归这是一棵n-ary树。

rowsum(input, gl(nrow(input) / 2, 2))/2

2 个答案:

答案 0 :(得分:1)

每个递归都可以设置为循环 对于深度搜索,您可以:

  1. 将根放入队列(先进先出)
  2. 在弹出队列时,您将项目的所有子项都放入队列
  3. 将项目保存在db
  4. 编辑:为每个请求添加代码

    var nodeQueue = new Queue<Node>();
    nodeQueue.Add(Tree.Root);
    while (!nodeQueue.Empty())
    {
        var item = nodeQueue.Pop();
        foreach(Node child in item.Children)
        {
            nodeQueue.Add(child);
        }
        db.Add(item.Data);
    }   
    

    另一种方式,将花费更多时间,计算树中的最大项目数量(我假设它可能不平衡)

    1. 在从0到MaxItems的循环中运行。
    2. 每个号码,转换为二进制。
    3. 左侧使用0,右侧使用1。
    4. 对于每个数字,相应地移动 那个树。 这样,每个数字代表树中的单个节点,您可以按特定顺序遍历树。
    5. 编辑:为每个请求添加代码

      var length = Tree.Count;
      var depth = Tree.Depth;
      var maxLength = Power(2,depth)-1
      for (var i=0; i<maxLength; i++)
      {
          db.Add(Tree.GetByNumber(i));
      }
      

      如果您想要更多编码答案(如果相关),请告诉我

答案 1 :(得分:0)

我创建了一种方法,可以将项目展平为可以递归处理的顺序,而无需使用递归。由于这是通用的扩展方法,因此可以用于任何事物。例如,您可以将T设为Action<>,以便您可以随时处理它们。这是扩展方法:

public static class EnumerableExtensions
{
    public static List<T> ToRecursiveOrderList<T>(this IEnumerable<T> collection, Expression<Func<T, IEnumerable<T>>> childCollection)
    {
        var resultList = new List<T>();
        var currentItems = new Queue<(int Index, T Item, int Depth)>(collection.Select(i => (0, i, 0)));
        var depthItemCounter = 0;
        var previousItemDepth = 0;
        var childProperty = (PropertyInfo)((MemberExpression)childCollection.Body).Member;
        while (currentItems.Count > 0)
        {
            var currentItem = currentItems.Dequeue();
            // Reset counter for number of items at this depth when the depth changes.
            if (currentItem.Depth != previousItemDepth) depthItemCounter = 0;
            var resultIndex = currentItem.Index + depthItemCounter++;
            resultList.Insert(resultIndex, currentItem.Item);

            var childItems = childProperty.GetValue(currentItem.Item) as IEnumerable<T> ?? Enumerable.Empty<T>();
            foreach (var childItem in childItems)
            {
                currentItems.Enqueue((resultIndex + 1, childItem, currentItem.Depth + 1));
            }
            previousItemDepth = currentItem.Depth;
        }

        return resultList;
    }
}

这里是如何使用它的示例。这样的结构将被展平。

  • A
  • B
  • C
    • D
      • E
    • F
    • G
    • H
  • J
    • K
    • L
      • M
  • N
  • O
    • P
    • Q
      • R
      • S
    • T
internal class Alpha
{
    public string Value { get; set; }
    public Alpha[] Children { get; set; }

    public override string ToString() => Value;
}

internal class Program
{
    public static void Main()
    {
        var items = new []
        {
            new Alpha { Value = "A" },
            new Alpha { Value = "B" },
            new Alpha { Value = "C", Children = new []
            {
                new Alpha { Value = "D", Children = new []
                {
                    new Alpha { Value = "E" },
                }},
                new Alpha { Value = "F" },
                new Alpha { Value = "G" },
                new Alpha { Value = "H", Children = new []
                {
                    new Alpha { Value = "I" },
                }},
            }},
            new Alpha { Value = "J", Children = new []
            {
                new Alpha { Value = "K" },
                new Alpha { Value = "L", Children = new []
                {
                    new Alpha { Value = "M" },
                }},
            }},
            new Alpha { Value = "N" },
            new Alpha { Value = "O", Children = new []
            {
                new Alpha { Value = "P" },
                new Alpha { Value = "Q", Children = new []
                {
                    new Alpha { Value = "R" },
                    new Alpha { Value = "S" },
                }},
                new Alpha { Value = "T" },
            }},
        };
        var ordered = items.ToRecursiveOrderList(a => a.Children);
        foreach (var item in ordered)
        {
            Console.WriteLine(item);
        }
    }
}

输出看起来像这样:

A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T