遍历树并使用可重用组件提取信息

时间:2017-09-23 21:07:13

标签: go

我在Go项目中有一个嵌套结构树。我想遍历树并执行不同的操作,例如在树中的不同级别挑选某些结构并将它们附加到列表中,或者修改结构。

我想使用可重用的组件来做这件事,这样我就可以专注于实现执行任务,而不必为每个这样的函数重新实现walker。到目前为止,我唯一能想到的就是这个API:

type applyFunc func(*Node)
func walker(node *Node, f applyFunc) {
     ....
     for _, child := range node.children() {
         walker(child, f)
     }
}

函数walker可以清楚地用于修改树,因为它传递指向树节点的指针。我喜欢它,因为我可以单独编写applyFunc函数,而不必费心实际的递归walker代码。但是,提取节点或删除节点更加困难。

为了从节点中提取信息,也许我可以使用闭包:

values := &[]int{}
f := func(node *Node) {
   values.append(node.val)
}
walker(root, f)
//values now hold the information I am interested in

这是一个很好的解决方案吗?还有更好的吗?

1 个答案:

答案 0 :(得分:1)

您还可以将walk函数添加到树类型中,在节点中添加指向父节点的指针,并将deleteChild方法添加到节点,该节点将子节点的索引作为参数,以便您轻松操作。 / p>

示例(这里我称为步行申请):

type node struct {
    children []*node
    parent   *node
    value    int
}

func (n *node) deleteChild(index int) {
    n.children = append(n.children[:index], n.children[index+1:]...)
}

func (n *node) delete(index int) {
    if n.parent != nil {
        n.parent.deleteChild(index)
    }
}

func (n *node) apply(index int, f func(int, *node)) {
    f(index, n)
    for childIndex, child := range n.children {
        child.apply(childIndex, f)
    }
}

func main() {
    t := &node{}
    t.children = []*node{
        &node{
            children: []*node{
                &node{value: 2},
            },
            value:    1,
            parent:   t,
        },
    }

    // extract all values in nodes
    values := []int{}
    t.apply(0, func(index int, n *node) {
        values = append(values, n.value)
    })
    fmt.Println(values) // [0 1 2]

    // delete a node
    fmt.Println(t.children) // [0xc4.....]
    t.apply(0, func(index int, n *node) {
        n.delete(index)
    })
    fmt.Println(t.children) // []
}