Arbres binaires équivalents – avec solutions
Il peut y avoir de nombreux arbres binaires différents contenant la même séquence de valeurs. Par exemple, voici deux arbres binaires stockant la séquence 1, 1, 2, 3, 5, 8, 13.
Dans la plupart des langages, il est assez complexe d’écrire une fonction permettant de vérifier si deux arbres binaires stockent la même séquence. Nous utilisons la concurrence et les canaux de Go pour écrire une solution simple et élégante.
Cet exemple utilise le package tree, qui définit le type :
type Tree struct {
Left *Tree
Value int
Right *Tree
}
Dans le code ci-dessous :
package main
import "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)
// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool
func main() {
}
- Implémentez la fonction
Walk - Testez la fonction
Walk- La fonction
tree.New(k)construit un arbre binaire structuré de manière aléatoire (mais toujours trié) contenant les valeurs \(k\), \(2k\), \(3k\), …, \(10k\). - Créez un nouveau canal
chet lancez le walker :go Walk(tree.New(1), ch) - Ensuite, lisez et imprimez 10 valeurs à partir du canal. Il devrait s’agir des nombres \(1\), \(2\), \(3\), …, \(10\).
- La fonction
- Implémentez la fonction
Sameen utilisantWalkpour déterminer si les arbrest1ett2stockent les mêmes valeurs - Testez la fonction
SameSame(tree.New(1), tree.New(1))devrait retournertrue, etSame(tree.New(1), tree.New(2))devrait retournerfalse.- La documentation de
Treese trouve ici.
Solution
package main
import (
"fmt"
"golang.org/x/tour/tree"
)
type Tree struct {
Left *Tree
Value int
Right *Tree
}
// 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) // <- 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)
}
// 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
// return false if the values are different
// or if one channel is closed and the other is not
if v1 != v2 || ok1 != ok2 {
return false
}
// return true if both channels are closed.
// We just have to test one channel, because we
// know that here, ok1 == ok2.
if !ok1 {
return true
}
}
}
func main() {
ch := make(chan int)
go func() {
Walk(tree.New(1), ch)
}()
for v := range ch {
fmt.Println(v)
}
fmt.Println(Same(tree.New(1), tree.New(1)))
fmt.Println(Same(tree.New(1), tree.New(2)))
}