I have a tree data-structure implemented in ruby. I’m using it to represent a parse-tree.
It works, as you might expect, by having many node objects, each containing useful values as well as an array of references to it’s child-nodes.
I’ve written a method to traverse the tree that’s pretty simple and works like:
def depth_first_traversal(node, &block)
if(node.has_children?)
depth_first_traversal(node.children[0], &block)
yield node
depth_first_traversal(node.children[1], &block)
else
yield node
end
end
The issue is that for each tree I only explicitly hold a reference to the root node. Thus far I’ve just been using my recursive traversal to access all the other nodes.
Now I need to change the values of the nodes in the tree and I’m not sure how to do it.
How could I modify this traversal so that I could modify each element in the tree, instead of just passing a reference to them in to &block?
— EDIT: —
Apologies for the lack of detail, I was trying to make my question broad and useful.
The ‘value’ of a node in the tree is several instance variables in each instance of the node-object. Lets call them @value and @type. There are getter and setter methods for them.
The tree is a binary tree – but that may change later. I also don’t think that’s the aspect of the problem I’m struggling with:
My tree explicitly creates the Node @root. All other nodes in the tree are created in a loop. So a typical node is accessible, for example as “the child of the child of the root” and in no other manner.
In other words, searching this structure of pointers is my only means of accessing the nodes.
If ruby passes exclusively by value, any value yielded (like in the above method) will be a copy of this object, not the object itself.
So I’m confused about how I should modify values in any tree, not just this one.
If I understand you correctly, you could probably do something like this:
Obviously this is going to have consequences to the tree structure, but that might be a benefit. The critical point here though is that you’re block will need to return a node instead of any old thing. Returning a string, for example, isn’t going to work the way that Array#map does, because a node inherently has children.
Another solution is to allow the map function to modify the contents of the node but not the structure. I’m taking a little liberty here as you didn’t post the instance variables nodes have access too, but it should make enough sense:
Here, I’m not passing the node itself to the block, but rather the contents. This way, the tree structure cannot be altered by the map. It seems like it might be more consistent with the Array#map function, but it might not do what you’re looking for.