tags:

views:

511

answers:

2

I found an implementation for a tree at this SO question. Unfortunately I don't know how to use it. Also I made a change to it since LinkedList does not have Add method:

delegate void TreeVisitor<T>(T nodeData);

class NTree<T>
{
    T data;
    List<NTree<T>> children;

    public NTree(T data)
    {
        this.data = data;
        children = new List<NTree<T>>();
    }

    public void AddChild(T data)
    {
        children.Add(new NTree<T>(data));
    }

    public NTree<T> GetChild(int i)
    {
        return children[i];
    }

    public void Traverse(NTree<T> node, TreeVisitor<T> visitor)
    {
        visitor(node.data);
        foreach (NTree<T> kid in node.children)
            Traverse(kid, visitor);
    }
}

I have class named tTable and I want to store it's children and their grandchildren (...) in this tree. My need is to find immediate children and not traverse entire tree. I also might need to find children with some criteria. Let's say tTable has only name and I want to find children with names matching some criteria. tTables constructor gives name a value according to int-value (somehow).

How do I use Traverse (write delegate) if I have code like this;

int i = 0;
Dictionary<string, NTree<tTable>> tableTreeByRootTableName = 
                  new Dictionary<string, NTree<tTable>>();
tTable aTable = new tTable(i++);
tableTreeByRootTableName[aTable.Name] = new NTree(aTable);
tableTreeByRootTableName[aTable.Name].AddChild(new tTable(i++));
tableTreeByRootTableName[aTable.Name].AddChild(new tTable(i++));

tableTreeByRootTableName[aTable.Name].GetChild(1).AddChild(new tTable(i++));
A: 

To get any benefit of using trees over lists or hash tables, there have to rules in place governing which nodes are children of parent nodes and not other parents and possibly the order in which the siblings occur. For example a binary search tree ensures that left children are less than the current node and right children are greater than the current node. This rule allows the binary search tree to get O(log n) search times. Similarly a heap guarantees that the root is greater than its children which gives it excellent sorting performance (worst case O(n log n)).

Your problem is insufficiently specified to grant any benefit to using a tree over another data structure.

Robert Davis
It looks like this tree isn't used for performance reasons; he's using it to establish the hierarchical relationship between items (something like XML). The tree is a fine structure for doing that.
Ron Warholic
Yes, but he wants to do an incomplete traversal to find a set of nodes that meet some criteria. This tree has no special internal structure, so the only way to find these nodes would be to do a complete traversal.
Robert Davis
While true, I imagine that he has more uses for this tree than this single traversal (at least I would hope so) in which case the tree might be advantageous.
Ron Warholic
@robert: this is what i need. there will be max 5 stages in the tree with only handfull of objects and I can make interruptive Traverse (see other answer's comments) and GetDirectChildren methods to make it perfect for me. Moreover I did not ask anything about tree theory. I've been to University also. I just want to store objects that have children to a simplest possible tree. I just wanted to know how to use the Traverse and delegate since I'm new to C#. That is why I 'insufficiently specified my problem'. Which I did not! You are just answering wrong question with wrong cocky answer (Add)
matti
@matti - __Your__ question specifically says, "My need is to find immediate children and not _traverse_ _entire_ _tree_." (Emphasis added) It's trivial to see that `Traverse()` does a full pre-order traversal of the tree. Thus it fails to meet your specified needs. I'm not responsible for giving a __correct__ answer to your __wrong__ question.
Robert Davis
+1  A: 

This code will traverse the tree and add all the nodes matching the given name. This is C# 3x, for 2.0 you'll need to use an anonymous delegate.

NTree<tTable> tree = new NTree<tTable>(table);

string nameToMatch = "SomeName";
LinkedList<tTable> matches = new LinkedList<tTable>();

tree.Traverse(tree, data => {
  if (data.Name == nameToMatch) {
    matches.AddLast(data);
  }
});
Ron Warholic
thanks ron! this arrow business is lambda expression, right? I try with anonymous delegate. I also can make another method TraverseInterrupt which interrupts the Traverse if the some conditions are filled. I think in that case I have to take the recursion into account and put some flag on that is checked and all the recursion levels return before foreach loops.
matti
Yes if you want this to terminate when you find a particular node add a return value to your TreeVisitor delegate that will allow you to stop the recursion when you return an appropriate value.
Ron Warholic