Last active
September 17, 2020 07:32
-
-
Save tcd93/683db769e577d387547269cf207dc146 to your computer and use it in GitHub Desktop.
Compare two binary trees using Goroutines
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
// solution to exercise from https://tour.golang.org/concurrency/7 | |
// if running local, execute `go get golang.org/x/tour/tree` beforehand | |
import ( | |
"fmt" | |
"golang.org/x/tour/tree" | |
) | |
//Walk Inorder Depth-First-Search | |
func Walk(t *tree.Tree, ch chan int, quit chan bool) { | |
node := t // the current node's pointer | |
stack := []*tree.Tree{} | |
for { | |
if node != nil { | |
stack = append(stack, node) | |
node = node.Left | |
} else if len(stack) > 0 { | |
var parent *tree.Tree | |
parent, stack = stack[len(stack)-1], stack[:(len(stack)-1)] // pop back the top node in stack & go right | |
ch <- parent.Value // signal a tree traversal event | |
node = parent.Right | |
} else { // done! send something to `quit` to signal a return | |
quit <- true | |
return | |
} | |
} | |
} | |
// Same determines whether the trees t1 and t2 contain the same values. | |
func Same(t1, t2 *tree.Tree, success chan bool) bool { | |
channel1 := make(chan int) // create channels with default buffer size 0 | |
channel2 := make(chan int) | |
quitSignal := make(chan bool) // a "bridge" channel to receive the done event from above channels | |
go Walk(t1, channel1, quitSignal) // kick off the Goroutine in a Green Thread | |
go Walk(t2, channel2, quitSignal) | |
for { // create a loop to listen to the communication channel with the above Goroutine | |
select { | |
case v1 := <-channel1: // receive a value from channel 1, then block `channel 1` (as it does not have a buffer specified) | |
v2 := <-channel2 //receive another value from Goroutine 2 to compare, then block `channel 2` | |
if v1 != v2 { | |
success <- false | |
return false | |
} | |
case <-quitSignal: | |
success <- true | |
return true | |
} | |
// now we're out of the current "select" | |
// the next iteration, with new "select" statement, will unblock the channels, and receive 1 new value from each of them | |
} | |
} | |
func main() { | |
tree1 := tree.New(2) // create a new tree | |
tree2 := tree.New(1) | |
signal := make(chan bool) | |
go Same(tree1, tree2, signal) // kick of the comparison in another Goroutine | |
success := <-signal // pause the main thread until signal received | |
fmt.Println(success) // should print False | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In Go, you can actually assign "nil" to pointers, but not concrete variables
Golang has not seems to implemented any solutions for the billion dollar mistake