二叉树遍历中的意外输出

时间:2021-07-07 10:49:28

标签: go concurrency channel

func New(k int) *Tree
// New() returns a random binary tree holding the values k, 2k, ..., 10k.

我只是在 goroutine 中尝试遍历二叉树并向通道添加值。然后在 main goroutine 中打印它们

代码

func binary(t *tree.Tree, ch chan int) {
    if t != nil {
        binary(t.Left, ch)
        ch <- t.Value
        binary(t.Right, ch)
    }
}

func Walk(t *tree.Tree, ch chan int) {
    defer close(ch)
    binary(t, ch)
}

func main() {
    ch := make(chan int)
    go Walk(tree.New(1), ch)
    for i := range ch {
        fmt.Printf("%d ", <-ch)
        _ = i
    }
}

预期输出 = 1 2 3 4 5 6 7 8 9 10

结果 = 2 4 6 8 10

2 个答案:

答案 0 :(得分:3)

通道上带有 for 子句的 range 语句接收来自通道的值并将它们存储在循环变量中。

意味着 i 变量将保存从 ch 接收的值,您不需要从 ch 接收。

然而,您没有使用 i,而且您确实从 ch 接收。因此,您将每隔一个元素跳过一次(如果频道上传递的元素数量为奇数,您也将面临被阻塞的风险)。

这样做:

for v := range ch {
    fmt.Printf("%d ", v)
}

答案 1 :(得分:-1)

基于icza的建议:

func binary(t *tree.Tree, ch chan int) {
    if t != nil {
        binary(t.Left, ch)
        ch <- t.Value
        binary(t.Right, ch)
    }
}

func Walk(t *tree.Tree, ch chan int) {
    defer close(ch)
    binary(t, ch)
}

func main() {
    ch := make(chan int)
    go Walk(tree.New(1), ch)
    for v := range ch {
    fmt.Printf("%d ", v)
    }
}