I've written some C# code to iterate through a Node[], listing all of its nodes in order (i.e. child elements are listed immediately after the parent).
Each Node is defined as follows,
class Node
{
public string Name { get; set; }
public List<Node> Children { get; set; } = new List<Node>();
public bool HasChildren => Children.Count > 0;
public Node(int n)
{
Name = $"Node #{n}";
}
public Node AddChild(Node n)
{
Children.Add(n);
return this;
}
public override string ToString() => Name;
}
The collection of nodes to be iterated would be,
var nodes = new Node[]
{
new Node(1),
new Node(2),
new Node(3)
.AddChild(new Node(4))
.AddChild(new Node(5))
.AddChild(new Node(6)
.AddChild(new Node(7)))
.AddChild(new Node(8)
.AddChild(new Node(9))
.AddChild(new Node(10)))
};
...and output for the above would be 10 lines of "Node #", each followed by the number passed to the constructor of each (i.e. 1 to 10, in ascending order).
The code I've written to perfom the aforementioned task is,
var stack = new Stack<(Node[], int)>();
var i = 0;
while (i < nodes.Length)
{
WriteLine($"{nodes[i]}");
if (nodes[i].HasChildren)
{
// Stores away the current Node[] and the next index, to return to it once all children are iterated though.
stack.Push((nodes, i + 1));
// Makes the child Node[] the iteration target.
nodes = nodes[i].Children.ToArray();
// Resets the index to iterate all the children.
i = 0;
continue;
}
// If the current node is the last in the targeted Node[], and there are parent Node[]s from which this Node[] was switched to in the stack.
if (i == nodes.Length - 1 && stack.Count > 0)
{
// Pop the stack until the popped Node[] isn't the last element, and assign it to the array being iterated.
var (_target, _i) = stack.Pop();
while (stack.Count > 0 && _i >= _target.Length)
{
(_target, _i) = stack.Pop();
}
nodes = _target;
i = _i;
continue;
}
++i;
}
Any criticism of my algorithm? Does it work for Node[]s of any depth (level of child-ception ;)? Ways in which it can be optimized?
(T1, T2) is a ValueTuple.
Node[]would cause a stack overflow, wouldn't it? \$\endgroup\$