Go Tour Exercise: Equivalent Binary Trees

前端 未结 23 1638
攒了一身酷
攒了一身酷 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:21

    This is how I did it, the difference is that you can wrap Walk into anonymous function and defer close(ch) inside it. Thus you have not to define other named recursive function

    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, ch2 := make(chan int), make(chan int)
        go func() {
            defer close(ch1)
            Walk(t1, ch1)
        }()
        go func() {
            defer close(ch2)
            Walk(t2, ch2)
        }()
        for {
            v1, ok1 := <- ch1
            v2, ok2 := <- ch2
            if ok1 != ok2 || v1 != v2 {
                return false
            }
            if !ok1 && !ok2 {
                break
            }
        }
        return true
    }
    
    func main() {
        ch := make(chan int)
        go func () {
            defer close(ch)
            Walk(tree.New(3), ch)
        }()
        for i := range ch {
            fmt.Println(i)
        }
    
        fmt.Println(Same(tree.New(1), tree.New(1)))
        fmt.Println(Same(tree.New(1), tree.New(2)))
        fmt.Println(Same(tree.New(10), tree.New(10)))
    }
    
    0 讨论(0)
  • 2020-12-13 00:24

    You should avoid to let opened channels unattended or a thread can be waiting forever and never ending.

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

    A clear answer:

    package main
    
    import "golang.org/x/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)
    }
    
    func WalkATree(t *tree.Tree, ch chan int) {
        Walk(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 WalkATree(t1, ch1)
        go WalkATree(t2, ch2)
        var v1, v2 int
        var ok1, ok2 bool
        for {
            v1, ok1 = <- ch1
            v2, ok2 = <- ch2
            if !ok1 && !ok2 {
                return true
            }
            if !ok1 && ok2 || ok1 && !ok2 {
                return false
            }
            if v1 != v2 {
                return false
            }
        }
    }
    
    func main() {
        fmt.Println(Same(tree.New(1), tree.New(1)))
    }
    
    0 讨论(0)
  • 2020-12-13 00:29
    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 {
        ch1, ch2 := make(chan int), make(chan int)
        go func() { Walk(t1, ch1); close(ch1) }()
        go func() { Walk(t2, ch2); close(ch2) }()
        for v1 := range ch1 {
            if v1 != <-ch2 {
                return false
            }
        }
        return true
    }
    
    func main() {
        fmt.Println(Same(tree.New(1), tree.New(1)))
        fmt.Println(Same(tree.New(2), tree.New(1)))
    }
    
    0 讨论(0)
  • An elegant solution using closure was presented in the golang-nuts group,

    func Walk(t *tree.Tree, ch chan int) {
        defer close(ch) // <- closes the channel when this function returns
        var walk func(t *tree.Tree)
        walk = func(t *tree.Tree) {
            if t == nil {
                return
            }
            walk(t.Left)
            ch <- t.Value
            walk(t.Right)
        }
        walk(t)
    }
    
    0 讨论(0)
  • 2020-12-13 00:30

    Tried to solve this problem using map structure.

    func Same(t1, t2 *tree.Tree) bool {
        countMap := make(map[int]int)
        ch := make(chan int)
        go Walk(t1, ch)
        for v := range ch {
            countMap[v]++
        }
        ch = make(chan int)
        go Walk(t2, ch)
        for v := range ch {
            countMap[v]--
            if countMap[v] < 0 {
                return false
            }
        }
        return true
    }
    
    0 讨论(0)
提交回复
热议问题