dousao2186 2017-09-23 21:07
浏览 21
已采纳

遍历树并提取具有可重用组件的信息

I have a tree of nested structs in a Go project. I would like to walk through the tree and perform different actions, such as picking out certain structs at different levels in the tree and appending them to a list, or modifying the structs in place.

I would like to do this using reusable components so that I can focus on implementing that perform the tasks, not having to reimplement the walker for every such function. So far the only thing I can think of is this API:

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

The function walker can clearly be used to modify the tree because it is passed pointers to the tree nodes. I like it because I can write applyFunc functions separately without having to bother with the actual recursive walker code. However, extracting nodes or deleting them is more difficult.

For extracting information from nodes, perhaps I can use a closure:

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

Would this be a good solution? Are there better ones?

  • 写回答

1条回答 默认 最新

  • dqxuiq7772 2017-09-23 21:41
    关注

    You could also add the walk function to your tree type, add a pointer to the parent in a node and add a deleteChild method to a node which takes the index of the child as argument which would allow you to manipulate easily.

    Example (here i called walk apply):

    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) // []
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 identifier of an instance of 类 was altered from xx to xx错误
  • ¥100 反编译微信小游戏求指导
  • ¥15 docker模式webrtc-streamer 无法播放公网rtsp
  • ¥15 学不会递归,理解不了汉诺塔参数变化
  • ¥30 软件自定义无线电该怎样使用
  • ¥15 R语言mediation包做中介分析,直接效应和间接效应都很小,为什么?
  • ¥15 Jenkins+k8s部署slave节点offline
  • ¥15 如何实现从tello无人机上获取实时传输的视频流,然后将获取的视频通过yolov5进行检测
  • ¥15 WPF使用Canvas绘制矢量图问题
  • ¥15 用三极管设计一个单管共射放大电路