C#遍历树并查找从根到叶的所有唯一层次结构链

时间:2018-03-26 20:24:15

标签: c# data-structures tree

我正在解决树问题而无法弄清楚如何解决手头的问题。我用Google搜索并检查了SO,但找不到 一个合适的方法,所以寻求专家社区的帮助。

问题是:

有一个类' Person',定义如下。该类跟踪给定Person的层次结构。

public class Person
{
    public string Name { get; set; }
    public List<Person> Children { get; set; }
}

现在,人物A&#39; A&#39;定义如下:

Person A = new Person()
{
    Name = "A",
    Children = new List<Person>()
    {
        new Person()
        {
            Name = "B",
            Children = new List<Person>()
            {
                new Person()
                {
                    Name = "E",
                    Children = null
                },
                new Person()
                {
                    Name = "F",
                    Children = new List<Person>()
                    {
                        new Person()
                        {
                            Name = "H",
                            Children = null
                        }
                    }
                }
            }
        },

        new Person()
        {
            Name = "C",
            Children = new List<Person>()
            {
                new Person()
                {
                    Name = "G",
                    Children = null
                }
            }
        },

        new Person()
        {
            Name = "D",
            Children = null
        }
    }
};

所以人&#39; A&#39;有3个孩子(B,C,D) &#39; B&#39;有2个孩子(E,F),
&#39; F&#39;有一个孩子(H),
&#39; C&#39;有一个孩子(G),
&#39; d&#39;没有孩子。

这个班可以在任何地方为任何人建模 现在给另一个班级,给定的人只能有一个孩子,如下:

public class PersonWithOneChildMax
{
    public string Name { get; set; }
    public PersonWithOneChildMax Child { get; set; }
}

如何获得Person&#39; A&#39;的层次结构链?在PersonWithOneChildMax&#39;?的对象方面较早 因此,最终结果将是一个PersonWithOneChildMax&#39;并将包含上述示例的4个对象。这4个对象将是:

PersonWithOneChildMax firstChain = new PersonWithOneChildMax()
{
    Name = "A",
    Child = new PersonWithOneChildMax()
    {
        Name = "B",
        Child = new PersonWithOneChildMax()
        {
            Name = "E",
            Child = null
        }
    }
};

PersonWithOneChildMax secondChain = new PersonWithOneChildMax()
{
    Name = "A",
    Child = new PersonWithOneChildMax()
    {
        Name = "B",
        Child = new PersonWithOneChildMax()
        {
            Name = "F",
            Child = new PersonWithOneChildMax()
            {
                Name = "H",
                Child = null
            }
        }
    }
};

PersonWithOneChildMax thirdChain = new PersonWithOneChildMax()
{
    Name = "A",
    Child = new PersonWithOneChildMax()
    {
        Name = "C",
        Child = new PersonWithOneChildMax()
        {
            Name = "G",
            Child = null
        }
    }
};

PersonWithOneChildMax fourthChain = new PersonWithOneChildMax()
{
    Name = "A",
    Child = new PersonWithOneChildMax()
    {
        Name = "D",
        Child = null
    }
};

简而言之,我正在寻找一种方法来获得人A的所有可能的层次结构:

A->B->E  
A->B->F->H  
A->C->G  
A->D 

如何获得最终结果,该结果将是&#39; PersonWithOneChildMax&#39;并将包含上面定义的4个对象 - &#39; firstChain&#39;, &#39; secondChain&#39;,&#39; thirdChain&#39;和&#39; FourthChain&#39; ?

为这个很长的问题道歉。

1 个答案:

答案 0 :(得分:0)

因此,请按照深度优先顺序浏览树,并保留您在此过程中访问过的节点列表。每当到达叶节点(没有子节点的人)时,创建一个层次结构并将其添加到结果列表中。

我还没有测试过这个,但基本的想法是:

public List<PersonWithOneChildMax> BuildFromPersonList(List<Person> people)
{
    var ancestors = new List<Person>();
    var result = new List<PersonWithOneChildMax>();
    foreach (person in people)
    {
        BuildDescendants(person, ancestors, result);
    }
    return result;
}

private void BuildDescendants(Person person, List<Person> ancestors, List<PersonWithOneChildMax> result)
{
    if (person.Children == null || person.Children.Count == 0)
    {
        var newPerson = new PersonWithOneChildMax {Name = person.Name, Child = null};
        // build the hierarchy backwards
        for (var i = ancestors.Count - 1; i >= 0; --i)
        {
            newPerson = new PersonWithOneChildMax {Name = ancestors[i].Name, Child = newPerson};
        }
        result.Add(newPerson);
    }
    else
    {
        ancestors.Add(person);
        foreach (var child in person.Children)
        {
            BuildDescendants(child, ancestors, result);
        }
        ancestors.RemoveAt(ancestors.Count-1);
    }
}