去游览树比较不起作用?

时间:2012-08-27 01:28:52

标签: concurrency go channel

我完成了树木比较的游览练习(#69),并且能够有效地比较两棵树。这是代码

    package main

    import "tour/tree"
    import "fmt"
    // Walk walks the tree t sending all values
    // from the tree to the channel ch.
    func Walk(t *tree.Tree, ch chan int) {
        if t == nil {
            return
        }
        Walk(t.Left,ch)
        ch <- t.Value
        Walk(t.Right,ch)
    }

    // Same determines whether the trees
    // t1 and t2 contain the same values.
    func Same(t1, t2 *tree.Tree) bool {
        c := make(chan int)
        c2 := make(chan int)
        go Walk(t1,c)
        go Walk(t2,c2)
        for i:= 0; i < 10; i++ {
            if <-c != <-c2 {
                return false
            }
        }
        return true
    }

    func main() {
        fmt.Println(Same(tree.New(1),tree.New(1)))
    }

令我困惑的是,如果我在walk函数中切换命令的顺序是

    ch <- t.Value
    Walk(t.Right,ch)
    Walk(t.Left,ch)

比较不再有效。我尝试打印出Walk的结果(tree.New(1),c)两次,奇怪的是第一次调用打印

    10,5,7,9...

而Walk的第二次调用(tree.New(1),c)打印

    7,9,10,8...

为什么在切换walk命令的顺序时,两次调用相同的函数会导致两个不同的输出?

2 个答案:

答案 0 :(得分:3)

首先,您需要了解树的属性。设置树以使左侧的数字始终小于当前节点的值。右边的数字总是更多。

因此,如果您想找到最小的数字,您需要做的就是在每个节点上“左”。如果你去最低号码的父母,你得到第二低。第二低的正确孩子可能是也可能不是第三低。但是,如果你从第二个最低的右孩子那里抓住每一次机会的左手,你将最终获得第三个最低点。这样做直到每个节点都被遍历。

当您Walk()树时,您实际上正在对数字进行排序。

Walk(t.Left,ch)
ch <- t.Value
Walk(t.Right,ch)

那就是左,现在,对。最低,第二低,第三低。

ch <- t.Value
Walk(t.Right,ch)
Walk(t.Left,ch)

这是当前的,右,左。第二低,第三低,最低。这种排序的问题在于它们的出现顺序取决于树的顺序。在第一个中,树中的元素而不是顺序是重要的。

Walk()函数实际实现的是树排序算法的一部分。请参阅:http://en.wikipedia.org/wiki/Tree_sort

答案 1 :(得分:1)

查看source code of Tree

// New returns a new, random binary tree
// holding the values 1k, 2k, ..., nk.
func New(n, k int) *Tree {
    var t *Tree
    for _, v := range rand.Perm(n) {
        t = insert(t, (1+v)*k)
    }
    return t
}

它使用Perm function

  

Perm作为一个n int的片段返回一个伪随机排列   整数[0,n)。

您看到的是一项功能:New创建的每棵树都是随机的。