這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
當初之所以學習Go語言,就是因為一句話:Golang天生支援並發。Java中的並發是一個比較複雜的系統,前段時間面試的時候,對於我這種CRUD Boy來說,理解並能應付並發方面的問題著實有些難度。各種概念背了一遍又一遍,current包下的東西來回練習,理解各種並發系統的設計理念,才能勉強應付一些比較水的面試。
經過幾天的學習,終於跟著Go指南,學到了並發一節。在這一節中,遇到的第一個練習是判斷等價二叉樹。
初始代碼如下
package mainimport "golang.org/x/tour/tree"// Walk 步進 tree t 將所有的值從 tree 發送到 channel ch。func Walk(t *tree.Tree, ch chan int)// Same 檢測樹 t1 和 t2 是否含有相同的值。func Same(t1, t2 *tree.Tree) boolfunc main() {}
對於Walk函數的實現,採用遞迴的前序走訪,基本沒什麼難度。
整體思路在一開始出現了一點偏差,主要是在Same函數的實現上。剛開始想的是兩個線程同時遍曆兩棵樹,在主線程中不斷的從兩個channel中取出數,當遇到不同的直接返回false。寫完後才意識到這樣只能判斷結構與資料都相同的二叉樹。
經過調整,借用map以數為鍵,值為該數出現的次數,第一個channel負責建立map,第二個channel負責比較
這個過程中還遇到了一個坑,就是channel的關閉。剛開始將close寫在了遞迴函式中,出現了panic。後將close該在遞迴函式外就可以。(很愚蠢的錯誤,哎)
package mainimport ("golang.org/x/tour/tree""fmt")// Walk 步進 tree t 將所有的值從 tree 發送到 channel ch。func Walk(t *tree.Tree, ch chan int){ch <- t.Valuefmt.Println(t.Value)if t.Left != nil{Walk(t.Left,ch)}if t.Right != nil{Walk(t.Right,ch)}}// Same 檢測樹 t1 和 t2 是否含有相同的值。func Same(t1, t2 *tree.Tree) bool{ch1 := make(chan int,10)ch2 := make(chan int,10)m := make(map[int]int)go func(){Walk(t1,ch1)close(ch1)}()go func(){Walk(t2,ch2)close(ch2)}()for{//將ch1的資料存入mapv,f:=<- ch1if f{k,_:=m[v]m[v]=k+1}else{break}}for{//比較ch1的資料v,f:=<-ch2if f {k,_:=m[v]if k == 0{return false}else{m[v]=k-1}}else{break}}return true}func main() {fmt.Println(Same(tree.New(2),tree.New(2)))}