'C# Traverse tree and find all unique hierarchy chains from root to leaf
I am working on a tree problem and not able to figure out how to solve the problem at hand. I've googled and also checked on SO, but could not find a suitable approach, so seeking help from the expert community.
Problem is this:
There is a class 'Person', defined like below. The class traces the hierarchy of a given Person.
public class Person
{
public string Name { get; set; }
public List<Person> Children { get; set; }
}
Now the hierarchy of a Person 'A' is defined like this:
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
}
}
};
So Person 'A' has 3 children (B,C,D).
'B' has 2 children (E,F),
'F' has 1 child (H),
'C' has 1 child (G),
'D' has no child.
And this class can model any person anywhere.
Now given another class where a given person can have only one child, like so:
public class PersonWithOneChildMax
{
public string Name { get; set; }
public PersonWithOneChildMax Child { get; set; }
}
How can I get hierarchy chains for Person 'A' earlier in terms of objects of 'PersonWithOneChildMax'?
So final result will be a list of 'PersonWithOneChildMax' and will contain 4 objects for the example above. Those 4 objects will be:
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
}
};
So in short, I am looking for a way to get all possible hierarchies for Person A:
A->B->E
A->B->F->H
A->C->G
A->D
How can I get the final result which will be a list of objects of type 'PersonWithOneChildMax' and will contain 4 objects defined above- 'firstChain', 'secondChain', 'thirdChain' and 'fourthChain' ?
Apologies for the very long question.
Solution 1:[1]
So walk the tree in depth-first order, keeping a list of the nodes you've visited along the way. Whenever you reach a leaf node (a person with no children), create a hierarchy and add it to the result list.
I haven't tested this, but the basic idea is:
public List<PersonWithOneChildMax> BuildFromPersonList(List<Person> people)
{
var ancestors = new List<Person>();
var result = new List<PersonWithOneChildMax>();
foreach (var 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);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | M. Mennan Kara |