Ruby:如何在树结构上实现.map方法?

时间:2012-12-08 00:33:13

标签: ruby map tree

我有一个用ruby实现的树数据结构。我用它代表一个解析树。

正如您所料,它有许多节点对象,每个节点对象包含有用的值以及对其子节点的引用数组。

我编写了一个遍历树的方法,这个方法非常简单,其工作原理如下:

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 

问题在于,对于每个树,我只显式保存对根节点的引用。到目前为止,我一直在使用我的递归遍历来访问所有其他节点。

现在我需要更改树中节点的值,我不知道该怎么做。 我怎么能修改这个遍历,以便我可以修改树中的每个元素,而不是只是将对它们的引用传递给&block?

---编辑:---
对于缺乏细节的道歉,我试图使我的问题广泛而有用。

树中节点的“值”是节点对象的每个实例中的几个实例变量。让我们称他们为@value@type。它们有getter和setter方法。

树是二叉树 - 但可能会在以后更改。我也不认为这是我正在努力解决的问题的方面:

我的树显式创建了节点@root。树中的所有其他节点都是在循环中创建的。因此,典型的节点是可访问的,例如作为“根的孩子的孩子”而不是其他方式。

换句话说,搜索指针结构是我访问节点的唯一方法。 如果ruby仅通过值传递,则产生的任何值(如上述方法中)将是此对象的副本,而不是对象本身。

所以我对如何修改任何树中的值感到困惑,而不仅仅是这个。

1 个答案:

答案 0 :(得分:0)

如果我理解正确,你可能会做这样的事情:

def df_tree_map(node, &block)
    if(node.has_children?)
        df_tree_map(node.children[0], &block)
        node = yield node
        df_tree_map(node.children[1], &block)
    else
        node = yield node
    end
end

显然这会对树结构产生影响,但这可能是一个好处。这里的关键点是你需要返回一个节点而不是任何旧节点。例如,返回一个字符串不会像Array#map那样工作,因为一个节点本身就有子节点。

另一种解决方案是允许map函数修改节点的内容而不是结构。我在这里采取一点自由,因为你没有发布实例变量节点也有访问权限,但它应该有足够的意义:

def df_tree_map(node, &block)
    if(node.has_children?)
        df_tree_map(node.children[0], &block)
        node.contents = yield node.contents
        df_tree_map(node.children[1], &block)
    else
        node.contents = yield node.contents
    end
end

这里,我没有将节点本身传递给块,而是将内容传递给块。这样,地图就不能改变树结构。看起来它可能与Array#map函数更加一致,但它可能无法满足您的需求。