C# 这个方法的大O符号是什么?

C# 这个方法的大O符号是什么?,c#,big-o,C#,Big O,我在我们的代码库中遇到过这个方法,我想知道最大的O是什么。该方法采用一个平面列表并创建一个树,在执行时指定父级和子级值 private void AddChildren(Group group, IEnumerable<Group> groups) { foreach (var g in groups) { if (g.ParentId == group.Id) { g.Parent = group;

我在我们的代码库中遇到过这个方法,我想知道最大的O是什么。该方法采用一个平面列表并创建一个树,在执行时指定父级和子级值

private void AddChildren(Group group, IEnumerable<Group> groups)
{
    foreach (var g in groups)
    {
        if (g.ParentId == group.Id)
        {
            g.Parent = group;
            group.Children.Add(g);
            AddChildren(g, groups);
        }
    }
}
private void AddChildren(组组、IEnumerable组)
{
foreach(组中的变量g)
{
if(g.ParentId==group.Id)
{
g、 父母=群体;
组。儿童。添加(g);
AddChildren(g,组);
}
}
}
除了识别直接的n^2(或更糟糕的)方法之外,我已经有一段时间没有做过大O了,但我对它的理解是这样的:

  • 我们迭代列表中的每个节点,得到n
  • 我们正在使用一个条件来处理被迭代项的子集。这里可能有多个匹配项,但不知道如何表示该数字,也不知道它如何修改AddChildren的递归调用
  • 我们有一些简单的赋值,我不知道这是否需要+1修饰符
  • 我们是递归的,但不是对封闭迭代中的每一项都递归
只是在外面扔点东西,让我看看自己是否在球场上:

n+(x*n)

其中x是if循环中的匹配数


如果您能想到这到底是什么,那就太好了,谢谢。

请注意,递归函数在每个父子关系中只调用一次。在有n个节点的树结构中,有n-1个这样的关系,因此
AddChildren()
被调用n次(包括初始调用)。在每次调用中,由于迭代,方法本身(不包括递归调用)执行的工作是O(n)。因此,O(n^2)总计


通过首先将所有组放在hashmap中,遍历列表一次,在hashmap中查找每个父节点,可以将复杂性提高到O(n)。

关于代码的运行顺序已经有很多讨论,因此我不会对此发表评论。艾斯蒙德·埃尔杜塞特的回答在我看来是正确的

也许你想要这样的东西,这是
O(n)

void AssignChildrenAndParent(IEnumerable组)
{
var groupById=新字典();
foreach(分组中的分组)
{
groupById.Add(group.Id,group);
}
foreach(分组中的分组)
{
Group parent=groupsById(Group.ParentId);
组。父=父;
parent.Children.Add(组);
}
}
这与原始代码的行为有些不同,因为它修复了所有父子关系,而不仅仅是根下的父子关系

或者,如果您确实希望代码的行为与原始代码完全相同(如果散列工作正常,则再次为O(n)):

private void AddChildren(组组、IEnumerable组)
{
var children=groups.ToLookup(group=>group.ParentId);
添加子项(组、组、查找);
}
私有void AddChildren(组组、IEnumerable组、查找)
{
foreach(查找[group.Id]中的变量g)
{
g、 父母=群体;
组。儿童。添加(g);
添加子项(g、组、查找);
}
}

家庭作业?就在今天,还有一个很大的递归问题。全班同学都要发帖了吗?为了确定这一点,我在发帖前权衡了一下家庭作业的反应。但老实说,除了不嵌套循环之外,在我构建的系统(CRUD业务应用程序)上,我真的不必太担心大O分析。这是我意识到的事情,但当我需要澄清我的想法时,我来到这里是为了那些在这件事上花费的时间比我多得多的人。只是说清楚,Big-O本身没有多大意义。您应该说明度量的内容:最坏情况下的性能、平均性能、最坏情况下的空间复杂度等。。。
void AssignChildrenAndParent(IEnumerable<Group> groups)
{

    var groupById=new Dictionary<GroupId,Group>();
    foreach(Group group in groups)
    {
      groupById.Add(group.Id,group);
    }
    foreach(Group group in groups)
    {
       Group parent=groupsById(group.ParentId);
       group.Parent=parent;
       parent.Children.Add(group);
    }
}
private void AddChildren(Group group, IEnumerable<Group> groups)
{
  var children=groups.ToLookup(group=>group.ParentId);
  AddChildren(group, groups, lookup); 
}

private void AddChildren(Group group, IEnumerable<Group> groups,Lookup<GroupId,Group> lookup)
{
    foreach (var g in lookup[group.Id])
    {
       g.Parent = group;
       group.Children.Add(g);
       AddChildren(g, groups,lookup);
    }
}