游览练习:等效二叉树

时间:2012-09-01 00:51:37

标签: go

我正试图在旅行中解决equivalent binary trees运动。这就是我所做的;

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.Left != nil {
        Walk(t.Left, ch)
    }
    ch <- t.Value
    if t.Right != nil {
        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 Walk(t1, ch1)
    go Walk(t2, ch2)
    for k := range ch1 {
        select {
        case g := <-ch2:
            if k != g {
                return false
            }
        default:
            break
        }
    }
    return true
}

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

然而,我无法找到如何在树木中留下更多元素的信号。我无法在close(ch)上使用Walk(),因为它会在所有值发送之前使通道关闭(因为递归。)任何人都可以帮我一把吗?

25 个答案:

答案 0 :(得分:90)

closure

中提供了使用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)
}

答案 1 :(得分:20)

这里是使用此处和Google Group主题

中的创意的完整解决方案
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)))

}

答案 2 :(得分:16)

如果您的Walk函数本身没有递归,您可以使用close()。即步行只会:

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

其中walkRecurse或多或少是你当前的Walk函数,但是在walkRecurse上递归。 (或者你重写Walk是迭代的 - 授予,更多是hazzle) 使用这种方法,您的Same()函数必须知道通道是closed,这是通过表单的通道接收来完成的

k, ok1 := <-ch
g, ok2 := <-ch

ok1ok2不同,或者false

时,请采取适当的措施

另一种方式,但可能不是在练习的精神,是计算树中节点的数量:

func Same(t1, t2 *tree.Tree) bool {
    countT1 := countTreeNodes(t1)
    countT2 := countTreeNodes(t2)
    if countT1 != countT2 {
        return false
    }
    ch1 := make(chan int)
    ch2 := make(chan int)
    go Walk(t1, ch1)
    go Walk(t2, ch2)
    for i := 0; i < countT1; i++ {
        if <-ch1 != <-ch2 {
            return false
        }
    }
    return true
}

你必须实现countTreeNodes()函数,它应该计算* Tree中节点的数量

答案 3 :(得分:7)

我就是这样做的,区别在于你可以将import Tkinter as tk import random class die(object): def __init__(self, value, display): self.value = random.randint(1,6) self.display = tk.Label(display, text = str(self.value), font = ('Garamond', 56), bg = 'white', relief = 'ridge', borderwidth = 5) self.display.pack(side = 'left') def rollDice(self): self.value = random.randint(1,6) print self.value #to show value is in fact changing self.display.config(text = str(self.value)) class DiceRoller(object): def __init__(self): self.gameWin = tk.Tk() self.gameWin.title('Dice Roller') self.gameFrame = tk.Frame(self.gameWin) self.dice = [] self.Row1 = tk.Frame(self.gameWin) for i in range(1,4): self.dice.append(die(i, self.Row1)) self.topFrame = tk.Frame(self.gameWin) self.rollBtn = tk.Button(self.topFrame, text = 'Roll Again', command = self.rollDice, font = ('Garamond', 56)) self.rollBtn.pack(side = 'bottom') self.gameFrame.pack() self.Row1.pack() self.topFrame.pack() self.gameWin.mainloop() def rollDice(self): for die in self.dice: die.rollDice() DiceRoller() 包装到匿名函数中并在其中包含Walk。因此,您不必定义其他命名的递归函数

defer close(ch)

答案 4 :(得分:3)

以下是我提出的解决方案:

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

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

func Same(t1, t2 *tree.Tree) bool{
    ch:=make(chan int)
    dh:=make(chan int)
    go Walk(t1,ch)
    go Walk(t2,dh)

    for i:=range ch {
        j,ok:=<-dh
        if(i!=j||!ok)  {return false} 
    }

    return true
}

答案 5 :(得分:2)

你得到的几乎是正确的,没有必要使用select语句,因为你经常会经历default这个案例,这是我的解决方案无需计算节点数发辫:

func Same(t1, t2 *tree.Tree) bool {
    ch1, ch2 := make(chan int), make(chan int)
    go Walk(t1, ch1)
    go Walk(t2, ch2)
    for i := range ch1 {
        j, more := <-ch2
        if more {
            if i != j { return false }
        } else { return false }
    }

    return true
}

答案 6 :(得分:2)

这是我的解决方法。

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))) 
}

答案 7 :(得分:2)

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)))
}

答案 8 :(得分:2)

这是我的解决方案。它适当地检查两个序列长度的差异。

package main

import "code.google.com/p/go-tour/tree"
import "fmt"

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

func Same(t1, t2 *tree.Tree) bool {
    chana := make (chan int)
    chanb := make (chan int)

    go Walk(t1, chana)
    go Walk(t2, chanb)

    for {
        n1, ok1 := <-chana
        n2, ok2 := <-chanb        
        if n1 != n2 || ok1 != ok2 {
            return false
        }
        if (!ok1) {
            break
        }
    }
    return true; 
}

答案 9 :(得分:2)

虽然我的第一个直觉是包裹递归步行和关闭频道,但我觉得这不符合练习的精神。

练习文本包含以下信息:

  

函数tree.New(k)构造一个随机结构化(但始终排序)的二叉树,其中包含值k, 2k, 3k, ..., 10k

其中明确指出生成的树只有10个节点。

因此,在本练习的精神和简洁性中,我采用了以下解决方案:

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)))
}

如果目标是在任意大小的树上运行,那么对封闭通道做出反应是更好的解决方案,但我觉得这是一个简单的练习,故意放置约束以使新Gopher更容易。

答案 10 :(得分:1)

之前的所有答案都没有解决有关Same功能的任务。问题是:

// Same determines whether the trees
// t1 and t2 contain the same values.
func Same2(t1, t2 *tree.Tree) bool

不应该考虑树的结构。这就是为什么跟随测试失败,在两行中都给出了错误:

fmt.Println("Should return true:", Same(tree.New(1), tree.New(1)))
fmt.Println("Should return false:", Same(tree.New(1), tree.New(2)))

记住?

  

函数tree.New(k)构造一个随机结构(但总是排序)的二叉树,其中包含值k,2k,3k,...,10k。

您只需检查两棵树是否具有相同的值。任务说明清楚地注意到:

Same(tree.New(1), tree.New(1))应返回trueSame(tree.New(1), tree.New(2))应返回false

因此,要解决此任务,您需要缓冲一棵树的所有结果,并检查第二棵树中的值是否在第一棵树中。

这是我的解决方案,它不是理想的:):

// 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)

    var tv1 = []int{}

    for v := range ch1 {
        tv1 = append(tv1, v)
    }

    inArray := func(arr []int, value int) bool {
        for a := range arr {
            if arr[a] == value {
                return true
            }
        }
        return false
    }

    for v2 := range ch2 {
        if !inArray(tv1, v2) {
            return false
        }
    }

    return true
}

答案 11 :(得分:1)

尝试使用地图结构来解决这个问题。

html = """<!DOCTYPE html>
<html>
<head>
    <title>Home</title>
</head>
<body>
    <h1>Welcome!</h1>
</body>
</html>"""

with open('html_file.html', 'w') as f:
    f.write(html)

import webbrowser, os
webbrowser.open('file://' + os.path.realpath('html_file.html'))

答案 12 :(得分:0)

这是一个非递归解决方案(即在大输入上不会有堆栈空间问题),它也不需要单独的访问地图 - 它只使用单个堆栈数据结构。避免访问过的地图的技巧是从堆栈中删除访问过的条目,而是为访问过的条目创建新的 tree.Tree 实例,删除左侧,这样它就不会重新访问左侧。

package main

import "fmt"
import "golang.org/x/tour/tree"

func Pop(stack []*tree.Tree) (*tree.Tree, []*tree.Tree) {
    last := len(stack) - 1
    node := stack[last]
    stack[last] = nil
    return node, stack[:last]
}

// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
    defer close(ch)
    stack := []*tree.Tree{t}
    var node *tree.Tree
    for len(stack) > 0 {
        node, stack = Pop(stack)
        if node.Left != nil {
            stack = append(stack, &tree.Tree{nil, node.Value, node.Right}, node.Left)
            continue
        }

        ch <- node.Value

        if node.Right != nil {
            stack = append(stack, node.Right)
        }
    }
}

// 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 {
            return false
        }
        if !ok1 || !ok2 {
            return ok1 == ok2
        }
    }
}

func PrintTree(t *tree.Tree) {
    ch := make(chan int)
    go Walk(t, ch)
    for i := range ch {
        fmt.Printf("%d ", i)
    }
    fmt.Println()
}

func main() {
    PrintTree(tree.New(1))
    PrintTree(&tree.Tree{Value: 1, Right: &tree.Tree{Value: 2}})

    fmt.Println("1 and 2 same (false): ", Same(tree.New(1), tree.New(2)))
    fmt.Println("1 and 1 same (true): ", Same(tree.New(1), tree.New(1)))
    fmt.Println("empty same (true): ", Same(&tree.Tree{}, &tree.Tree{}))
    fmt.Println("diff length same (false): ", Same(&tree.Tree{Value: 1}, &tree.Tree{Value: 2, Left: &tree.Tree{Value: 2}}))
}

输出为:

1 2 3 4 5 6 7 8 9 10 
1 2 
1 and 2 same (false):  false
1 and 1 same (true):  true
empty same (true):  true
diff length same (false):  false

答案 13 :(得分:0)

如果一个人正在使用带有 Walk 逻辑的递归调用,并且希望向渠道消费者发出信号表明没有更多项目,那么似乎可以将大部分 Walk 逻辑放入第二个函数,调用第二个函数,等待它完成,然后关闭通道。

在下面的示例中,第二个(“inner Walk”)函数是一个直接位于 Walk 函数内部的“闭包”,但并非必须如此。

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) {
    defer close(ch)
    var iw func(*tree.Tree)
    iw = func(it *tree.Tree) {
        if it == nil {
            return
        }
        iw(it.Left)
        ch <- it.Value
        iw(it.Right)
    }
    iw(t)
}

// 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 {
        v1, more1 := <- ch1
        v2, more2 := <- ch2
        if (!more1 && !more2) {
            return true
        }
        if more1 != more2 || v1 != v2 {
            return false
        }
    }
}

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

答案 14 :(得分:0)

到目前为止,在该线程中还没有看到它。我使用了just for func

中介绍的nil频道技术

关闭通道的问题已通过在goroutine实例中启动它们来解决。

我想我可以检查更多表现出色的人。

package main

import (
    "fmt"
    "reflect"
    "sort"

    "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) {
    ch <- t.Value
    if t.Right != nil {
        Walk(t.Right, ch)
    }
    if t.Left != nil {
        Walk(t.Left, ch)
    }

}

// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool {

    c1 := make(chan int)
    s1 := []int{}

    go func() {
        Walk(t1, c1)
        close(c1)
    }()

    c2 := make(chan int)
    s2 := []int{}

    go func() {
        Walk(t2, c2)
        close(c2)
    }()

    for c1 != nil || c2 != nil {
        select {
        case v, ok := <-c1:
            if !ok {
                c1 = nil
                sort.Ints(s1)
                continue
            }
            s1 = append(s1, v)
        case v, ok := <-c2:
            if !ok {
                c2 = nil
                sort.Ints(s2)
                continue
            }
            s2 = append(s2, v)
        }
    }
    return reflect.DeepEqual(s1, s2)
}

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

答案 15 :(得分:0)

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) {
    walkRecursive(t, ch)
    close(ch)
}

func walkRecursive(t *tree.Tree, ch chan int) {
    if t == nil {
        return
    }
    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 {
    ch1 := make(chan int)
    ch2 := make(chan int)
    go Walk(t1, ch1)
    go Walk(t2, ch2)

    for {
        v1, ok1 := <-ch1
        v2, ok2 := <-ch2
        if ok1 != ok2 {
            return false
        }
        if !ok1 {
            return true
        }
        if v1 != v2 {
            return false
        }
    }
}

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

答案 16 :(得分:0)

这是我的解决方案,没有defer的魔力。我认为这会更容易阅读,所以值得分享:)

奖金:此版本实际上解决了巡演中的问题并给出了适当的结果。

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)))
}

所以输出如下:

1
2
3
4
5
6
7
8
9
10
false
true
false

答案 17 :(得分:0)

一个明确的答案:

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)))
}

答案 18 :(得分:0)

对于有兴趣的人,如果你想知道如何在不创建单独的递归函数的情况下解决这个问题,这里是一个使用堆栈的答案:

func Walk(t *tree.Tree, ch chan int) {
    defer close(ch)
    visitStack := []*tree.Tree{t}
    visited := make(map[*tree.Tree]bool, 1)
    for len(visitStack) > 0 {
        var n *tree.Tree
        n, visitStack = visitStack[len(visitStack)-1], visitStack[:len(visitStack)-1]
        if visited[n] {
            ch <- n.Value
            continue
        }
        if n.Right != nil {
            visitStack = append(visitStack, n.Right)
        }
        visitStack = append(visitStack, n)
        if n.Left != nil {
            visitStack = append(visitStack, n.Left)
        }
        visited[n] = true
    }
}

答案 19 :(得分:0)

这里的解决方案并不依赖于不同的树长度,也不依赖于遍历顺序:

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) {
    var walk func(*tree.Tree)
    walk = func(tr *tree.Tree) {
        if tr == nil {
            return
        }

        walk(tr.Left)
        ch <- tr.Value
        walk(tr.Right)
    }

    walk(t)
    close(ch)
}

func merge(ch chan int, m map[int]int) {
    for i := range ch {
        count, ok := m[i]
        if ok {
            m[i] = count + 1
        } else {
            m[i] = 1
        }
    }
}

// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool {
    ch1 := make(chan int, 100)
    ch2 := make(chan int, 100)
    m := make(map[int]int)

    go Walk(t1, ch1)
    go Walk(t2, ch2)

    merge(ch1, m)
    merge(ch2, m)

    for _, count := range m {
        if count != 2 {
            return false
        }
    }

    return true
}

答案 20 :(得分:0)

因为问题只是说树只有10个节点,所以在阅读其他答案后,我的回答是:

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

    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)
}

func Same(t1, t2 *tree.Tree) bool {
    ch1, ch2 := make(chan int), make(chan int)
    go Walk(t1, ch1)
    go Walk(t2, ch2)

    for range make([]struct{}, 10) {
        if <-ch1 != <-ch2 {
            return false
        }
    }
    return true
}

答案 21 :(得分:0)

这就是我使用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))
}

答案 22 :(得分:0)

我写了两个版本,总是把两个频道都读到最后:

package main

import (
    "fmt"
    "golang.org/x/tour/tree"
)

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)
}

func Same(t1, t2 *tree.Tree, sameChan func(ch1, ch2 chan int) bool) bool {
    ch1, ch2 := make(chan int), make(chan int)
    go Walk(t1, ch1)
    go Walk(t2, ch2)

    return sameChan(ch1, ch2)
}

func sameChan1(ch1, ch2 chan int) bool {
    areSame := true
    for {
        v1, ok1 := <-ch1
        v2, ok2 := <-ch2

        if !ok1 && !ok2 {
            return areSame
        }

        if !ok1 || !ok2 || v1 != v2 {
            areSame = false
        }
    }
}

func sameChan2(ch1, ch2 chan int) bool {
    areSame := true
    for v1 := range ch1 {
        v2, ok2 := <-ch2

        if !ok2 || v1 != v2 {
            areSame = false
        }
    }
    for _ = range ch2 {
        areSame = false
    }
    return areSame
}

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

    fmt.Println(Same(tree.New(1), tree.New(1), sameChan2))
    fmt.Println(Same(tree.New(2), tree.New(1), sameChan2))
    fmt.Println(Same(tree.New(1), tree.New(2), sameChan2))
}

答案 23 :(得分:0)

我的版本

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)))
}

答案 24 :(得分:0)

你应该避免让打开的频道无人看管,或者线程可以永远等待,永远不会结束。

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)))
}