Go Tour Exercise: Equivalent Binary Trees

前端 未结 23 1639
攒了一身酷
攒了一身酷 2020-12-12 23:39

I am trying to solve equivalent binary trees exercise on go tour. Here is what I did;

package main

import \"tour/tree\"
import \"fmt\"

// Walk walks the tr         


        
相关标签:
23条回答
  • 2020-12-13 00:30

    My version

    package main
    
    
    import (
        "fmt"
        "golang.org/x/tour/tree"
    )
    
    // Walk walks the tree t sending all values
    // from the tree to the channel ch.
    func WalkRec(t *tree.Tree, ch chan int) {
        if t == nil {
            return
        }
        WalkRec(t.Left, ch)
        ch <- t.Value
        WalkRec(t.Right, ch)
    }
    
    func Walk(t *tree.Tree, ch chan int) {
        WalkRec(t, ch)
        close(ch)
    }
    
    // Same determines whether the trees
    // t1 and t2 contain the same values.
    func Same(t1, t2 *tree.Tree) bool {
        ch1 := make(chan int)
        ch2 := make(chan int)
        go Walk(t1, ch1)
        go Walk(t2, ch2)
    
        for {
            x, okx := <-ch1
            y, oky := <-ch2
            switch {
            case okx != oky:
                return false
            case x != y:
                return false
            case okx == oky && okx == false:
                return true
            }
    
        }
    
    }
    
    func main() {
        ch := make(chan int)
        go Walk(tree.New(1), ch)
        fmt.Println(Same(tree.New(1), tree.New(1)))
        fmt.Println(Same(tree.New(2), tree.New(1)))
        fmt.Println(Same(tree.New(1), tree.New(2)))
    }
    
    0 讨论(0)
  • 2020-12-13 00:31

    While my first intuition was to also wrap the recursive walk and closing the channels, I felt it was not in the spirit of the exercise.

    The exercise text contains the following information:

    The function tree.New(k) constructs a randomly-structured (but always sorted) binary tree holding the values k, 2k, 3k, ..., 10k.

    Which clearly states that the resulting trees have exactly 10 nodes.

    Therefore, in the spirit and simplicity of this exercise, I went with the following solution:

    package main
    
    import (
        "fmt"
        "golang.org/x/tour/tree"
    )
    
    func Walk(t *tree.Tree, ch chan int) {
        if t.Left != nil {
            Walk(t.Left, ch)
        }
        ch <- t.Value
        if t.Right != nil {
            Walk(t.Right, ch)
        }
    }
    
    func Same(t1, t2 *tree.Tree) bool {
        ch1 := make(chan int)
        ch2 := make(chan int)
    
        defer close(ch1)
        defer close(ch2)
    
        go Walk(t1, ch1)
        go Walk(t2, ch2)
    
        for i := 0; i < 10; i++ {
            if <-ch1 != <-ch2 {
                return false
            }
        }
    
        return true
    }
    
    func main() {
        fmt.Println(Same(tree.New(1), tree.New(2)))
    }
    

    If the goal would be to run on arbitrarily sized trees, then reacting to closed channels is the better solution, but I felt this was a simple exercise with intentionally put constraints to make it easier for the new Gopher.

    0 讨论(0)
  • 2020-12-13 00:33

    Here's the full solution using ideas here and from the Google Group thread

    package main
    
    import "fmt"
    import "code.google.com/p/go-tour/tree"
    
    // Walk walks the tree t sending all values
    // from the tree to the channel ch.
    func Walk(t *tree.Tree, ch chan int) {
        var walker func(t *tree.Tree)
        walker = func (t *tree.Tree) {
            if (t == nil) {
                return
            }
            walker(t.Left)
            ch <- t.Value
            walker(t.Right)
        }
        walker(t)
        close(ch)
    }
    
    // Same determines whether the trees
    // t1 and t2 contain the same values.
    func Same(t1, t2 *tree.Tree) bool {
        ch1, ch2 := make(chan int), make(chan int)
    
        go Walk(t1, ch1)
        go Walk(t2, ch2)
    
        for {
            v1,ok1 := <- ch1
            v2,ok2 := <- ch2
    
            if v1 != v2 || ok1 != ok2 {
                return false
            }
    
            if !ok1 {
                break
            }
        }
    
        return true
    }
    
    func main() {
        fmt.Println("1 and 1 same: ", Same(tree.New(1), tree.New(1)))
        fmt.Println("1 and 2 same: ", Same(tree.New(1), tree.New(2)))
    
    }
    
    0 讨论(0)
  • 2020-12-13 00:33

    That's how I did it using Inorder Traversal

    package main
    
    import (
        "fmt"
        "golang.org/x/tour/tree"
    )
    
    // 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 {
            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 {
        c1, c2 := make(chan int), make(chan int)
        go Walk(t1, c1)
        go Walk(t2, c2)
        if <-c1 == <-c2 {
            return true
        } else {
            return false
        }
    }
    
    func main() {
        t1 := tree.New(1)
        t2 := tree.New(8)
        fmt.Println("the two trees are same?", Same(t1, t2))
    }
    
    0 讨论(0)
  • 2020-12-13 00:34

    This is my solution.

    package main
    
    import (
      "golang.org/x/tour/tree"
      "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 {
        ch1 := make(chan int)
        ch2 := make(chan int)
        
        go func() {
            Walk(t1, ch1)
            close(ch1)
        }()
        
        go func() {
            Walk(t2, ch2)
            close(ch2)
        }()
        
        for {
            v1, ok1 := <- ch1
            v2, ok2 := <- ch2
            
            if ok1 == false && ok2 == false {
                return true
            }
            
            if v1 != v2 {
                return false
            }
        }
    
        return false
    }
    
    func main() {
        fmt.Println(Same(tree.New(1), tree.New(1))) 
        fmt.Println(Same(tree.New(1), tree.New(2))) 
    }
    
    
    0 讨论(0)
  • 2020-12-13 00:34

    Here's my solution, without the defer magic. I thought this would be a bit easier to read, so it would worth sharing :)

    Bonus: This version actually solves the problem in the tour's exercise and gives proper results.

    package main
    
    import (
        "golang.org/x/tour/tree"
        "fmt"
    )
    
    // Walk walks the tree t sending all values
    // from the tree to the channel ch.
    func Walk(t *tree.Tree, ch chan int) {
        walkRecursive(t, ch)
        close(ch)
    }
    
    func walkRecursive(t *tree.Tree, ch chan int) {
        if t != nil {
            walkRecursive(t.Left, ch)
            ch <- t.Value
            walkRecursive(t.Right, ch)
        }
    }
    
    // Same determines whether the trees
    // t1 and t2 contain the same values.
    func Same(t1, t2 *tree.Tree) bool {
        var br bool
        ch1, ch2 := make(chan int), make(chan int)
        go Walk(t1, ch1)
        go Walk(t2, ch2)
    
        for i:= range ch1 {
            if i == <-ch2 {
                br = true
            } else {
                br = false
                break
            }
        }
        return br
    }
    
    func main() {
        ch := make(chan int)
        go Walk(tree.New(1), ch)
    
        for i := range ch {
            fmt.Println(i)
        }
    
        fmt.Println(Same(tree.New(1), tree.New(2)))
        fmt.Println(Same(tree.New(1), tree.New(1)))
        fmt.Println(Same(tree.New(2), tree.New(1)))
    }
    

    So the output is as follows:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    false
    true
    false
    
    0 讨论(0)
提交回复
热议问题