<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
樹的反序列化故名知意就是將一個序列化成字串或者其它形式的資料重新的生成一顆二元樹,如下這顆二元樹將它序列化成字串後的結果[5,4,null,null,3,2,1],而現在要做的是要將這個字串重新的生成一顆二元樹(生成下面這顆樹,因為這個字串就是通過這顆樹序列化來的)。
null
來表示的空,比如上面節點2下面沒有資料,在字串中就用了null
來表示split
方法來分割成陣列FIFO
的特性,在處理完左支的時候能夠放便的拿到右支的node這個裡面的資料很容易就看懂,val是當前節點的資料;left ,right分別儲存的是左支和右支的資料
針對每個資料生成對應的TreeNode
func GenerateNode(str string) *TreeNode { if str == "null" { return nil } return &TreeNode{val: str} }
這個方法主要是生成TreeNode物件的方法,上面說到當節點下面沒有子節點的時候就會用null來表不,所以這裡接收到的形參如果是null的話就會反回一個空指標,相反如果不是null就會反回一個建立的TreeNode物件,並將val屬性賦值
func DeserializationTb(dataQueue []string) (resultNode *TreeNode) { if len(dataQueue) == 0 { return nil } var tempNodeQueue []*TreeNode resultNode = generateNode(dataQueue[len(dataQueue) - 1]) dataQueue = dataQueue[:len(dataQueue) - 1] if resultNode != nil { tempNodeQueue = append(tempNodeQueue,resultNode) } var tempNode *TreeNode for len(tempNodeQueue) != 0 { tempNode = tempNodeQueue[0] tempNodeQueue = tempNodeQueue[1:] if len(dataQueue) > 0 { tempNode.left = generateNode(dataQueue[len(dataQueue) - 1]) dataQueue = dataQueue[:len(dataQueue) - 1] tempNode.right = generateNode(dataQueue[len(dataQueue) - 1]) dataQueue = dataQueue[:len(dataQueue) - 1] } if tempNode.left != nil { tempNodeQueue = append(tempNodeQueue,tempNode.left) } if tempNode.right != nil { tempNodeQueue = append(tempNodeQueue,tempNode.right) } } return }
這個方法的程式碼比較多,這裡就會塊來說一下:
if len(dataQueue) == 0 { return nil }
這幾行程式碼無非就是一個邊界條件的判斷的問題,當傳來的佇列沒有資料的時候就返回一個空,為啥是佇列?因為我將字串轉成了佇列
var tempNodeQueue []*TreeNode resultNode = generateNode(dataQueue[len(dataQueue) - 1]) dataQueue = dataQueue[:len(dataQueue) - 1] if resultNode != nil { tempNodeQueue = append(tempNodeQueue,resultNode) }
var tempNodeQueue []*TreeNode
:這裡建立一個TreeNode指標陣列的原因是儲存要操作節點的資料,因為我將序列化後的資料轉成了佇列,所以在這個陣列中最後一個元素應該是先出來的陣列,同樣第一個出來的資料是這顆二元樹的根節點,將這個節點儲存到了這個佇列裡面,然後這個佇列將在下面的for迴圈中使用到,其餘的下面再說.
resultNode = generateNode(dataQueue[len(dataQueue) - 1])
:這裡便是將出佇列,並通過generateNode
生成一個TreeNode物件
dataQueue = dataQueue[:len(dataQueue) - 1]
:因為有一個陣列已經出了佇列,就要將其去掉
tempNodeQueue = append(tempNodeQueue,resultNode)
:經過一個判空處理,便將這個節點儲存到了上面提到的佇列裡面
for len(tempNodeQueue) != 0 { tempNode = tempNodeQueue[0] tempNodeQueue = tempNodeQueue[1:] if len(dataQueue) > 0 { tempNode.left = generateNode(dataQueue[len(dataQueue) - 1]) dataQueue = dataQueue[:len(dataQueue) - 1] tempNode.right = generateNode(dataQueue[len(dataQueue) - 1]) dataQueue = dataQueue[:len(dataQueue) - 1] } if tempNode.left != nil { tempNodeQueue = append(tempNodeQueue,tempNode.left) } if tempNode.right != nil { tempNodeQueue = append(tempNodeQueue,tempNode.right) } }
當進入For迴圈後,也就證明現在這個佇列裡面有資料,不管三七二十一,先將裡面的資料彈出,因為只有有了資料才可以進行下面的操作(無資料,不程式設計)
tempNodeQueue = tempNodeQueue[1:]
:因為前一行程式碼將資料在這個佇列裡面彈出了, 所以一行程式碼是將已彈出的資料去除
tempNode.left = generateNode(dataQueue[len(dataQueue) - 1])
:當傳來序列化二元樹的存在資料的時候就將其節點的left , right分支進麼賦值,下一行程式碼就是將彈出的資料去除,接下來的兩行便是對right節點的處理,同left一樣
tempNodeQueue = append(tempNodeQueue,tempNode.left)
:如果tempNode的左節點存在的時候就將其儲存到佇列中,遍歷tempNodeQueue
佇列,再次執行上面的步驟.
可能有小夥伴存在疑問?
所返回的resultNode
變數只賦值過一次,那子節點是如何賦值的呢?因為所有的TreeNode的節點我都是通過指標來處理的,
而在For裡面的第一行程式碼所彈出的資料指向的地址正是resultNode
的地址,所以在生成完樹之後,我只要抓住這顆樹的根節點就好了
樹的序列化又是怎麼一回事呢?我可以將這顆樹轉換成一定格式的資料結構,比如:轉換成一段文字可以持久化到硬碟中。
那有什麼作用呢?比如Redis
中的資料是在記憶體中的,它有一個功能是每隔一段 時間可以將資料儲存到硬碟中以防止突發的斷電導至資料的丟失
這裡說的樹的序列化你也可以這樣的理解,我要將一顆二元樹裡面的資料序列化儲存到硬碟,以便下次使用這裡面的數的據的時候可以直接生成這顆樹
null
來表示的/** 序列化二元樹 */ func SerializationTb(bt *TreeNode) (saveSerData []string) { root := bt var tempQueue []*TreeNode if root != nil { tempQueue = append(tempQueue, root) } var tempNode *TreeNode for len(tempQueue) != 0 { tempNode = tempQueue[0] if tempNode != nil { saveSerData = append(saveSerData, tempNode.val) } else { saveSerData = append(saveSerData, "null") } tempQueue = tempQueue[1:] if tempNode != nil { tempQueue = append(tempQueue, tempNode.left) tempQueue = append(tempQueue, tempNode.right) } } return }
這些程式碼還是很好看懂的,這裡就說下for裡面的程式碼吧~~
tempNode = tempQueue[0]
:在佇列裡面彈出一個資料
saveSerData = append(saveSerData, tempNode.val)
:將tempNode
的val屬性儲存到saveSerData
佇列裡面
下面的if
就是判斷當這個節點為空或者是不為空的時候需要分別怎麼處理資料,上面說到如果一個節點下面沒有子節點,這裡就用null
來表示,所以當沒有子節點的時候就用將null新增到佇列裡面
tempQueue = tempQueue[1:]
:對佇列重新賦值,將彈出的那個資料去掉
tempQueue = append(tempQueue, tempNode.left)
:將左節點加入到佇列裡面,下一行同理
到此這篇關於go語言實現二元樹的序例化與反序列化的文章就介紹到這了,更多相關go序例化內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45