Main menu:

Site search

Categories

March 2010
M T W T F S S
« Jan    
1234567
891011121314
15161718192021
22232425262728
293031  

Tags

Blogroll

Recursive Trees

I like recursive algorithms, and I like trees (I mean the data structure, not the perennial wooden plant - of course I like them too). So today, I was very glad when I had the chance to implement one on my current project. 

The main construct of the tree is the node. Generally, the node is comprised of the data which describes the node, and a list of all children nodes. For example, in the tree below, node 6 (the circle with 6 in it) has the children node 5 and node 11, and has the data of 6.

There a certain descriptors of a tree, and their use is context specific. One such descriptor would be the root node – a node without any parents. The root node for this tree is node 2 (the one at the top). Another descriptor would be leaf nodes – nodes without any children. The leaf nodes for this tree are nodes 2, 5, 11 and 4. 

For my project, I had to create my tree from the data in a structure similar to : [ [7, 2], [7, 6, 5], [7, 6, 11], [5, 9, 4] ], where the root node was empty (not 2 as in this diagram). Creating the tree was easy with the help of a little recursion and the use of a stack.

public void BuildTree(List data)
{
	Node rootNode = new Node()
	for each (List treePath in data)
	{
		rootNode.AddChild(treePath as Stack)
	}
}

public class Node
{
	private string _name;
	private List<Node> _children = new List<Node>();

	public void AddChild(Stack path)
	{
		Node child = FindOrCreate(path.pop())
		if (path.Count > 0)
		{
			child.AddChild(path)
		}
	}

	private void FindOrCreate(string name)
	{
		Maybe<Node> child = _children.Find(name)
		if (child.IsPresent)
		{
			return child.Force()
			// if you haven't seen my post on maybe objects, this will return the child node
		}
		return CreateChild(name)
	}

	private void CreateChild(string name)
	{
		Node child = new Node(name)
		_children.Add(child)
		return child
	}
}

Persisting this is not as complicated as we first thought. When kicking around persistence ideas, we talked about using Oracle’s parent-child recursive constraints. But, all you need is a Node table [int id; string name] which holds the data for each Node, and a mapping table (I called it a parentage table) [int parent_Id; int child_Id] which holds the relationship between parent and child node. Voila! No need of recursive constraints within the database layer.

Recursion is a really powerful tool, and as I proved to myself, trees are actually quite easy to persist.

Comments

Comment from Jim
Time October 15, 2008 at 11:16 pm

Maybe? Is that some kind of null object? If so it looks awesome!

Comment from Sarah
Time October 16, 2008 at 7:00 am

A maybe object represents an object which may or may not be present. If an object is not present, and you were just returning the object itself (as in: did not use maybes) then it would be null.
One advantage of the maybe is that it makes your code that much more declarative rather than just a null check.
More info here: Maybe Null

Comment from Rupert
Time October 16, 2008 at 7:05 am

For persistence (depending on how you are using the tree) if speed of access is more important than speed of writing you might want to look at using nested sets as these allow you to do things like get a node and all of it’s children with a single query.

Comment from Sarah
Time October 16, 2008 at 9:49 am

Thanks Rupert.
I will keep this in mind if I run into performance issues.

Comment from Jim
Time October 16, 2008 at 4:08 pm

On second thoughts, it doesn’t look quite so awesome. I was thinking it would be a replacement for boilerplate NullXXX classes. It does make it clear that the method may return null, but I still don’t like the unboxing into the “real” object.

Write a comment