本文共 4486 字,大约阅读时间需要 14 分钟。
这篇略长,大家耐心点
这个可视化好看些
总的来说:序列化可以基于先序/ 中序/ 后序/ 按层
等遍历方式进行 思路1、2是层序,思路3是先序 这里分两部分讲
序列化的字符串实际上是二叉树的 “层序遍历”(BFS 广度优先遍历)结果,参见
先上图
再看代码''' # 和 null 都行,都表示空,但要统一,要么全用'#',要么全用null。'''class Codec: # 1.序列化 def serialize(self, root): ans = '' queue = [root] while queue: node = queue.pop(0) if node: ans += str(node.val) + ',' queue.append(node.left) queue.append(node.right) else: # 除了这里不一样,其他和普通的不记录层的 BFS 没区别 ans += '#,' # print(ans[:-1]) return ans[:-1] # 末尾会多一个逗号,我们去掉它。
注意
:在 序列化函数 中 ans 是 str 类型,执行ans += str(node.val) + ','后,
. . 而后在 反序列化函数 中,ans = 1,2,3,#,#,4,5,#,#,#,#
也是一个 str 类型的字符串,该字符串 长度为为 21 (逗号也是一个元素,这里跟 列表list 不一样)nodes = data.split(',') # 通过 ',' 分隔每个元素,可以得到 11 个节点的列表通过 ‘,’ 分隔每个元素,得到 11 个节点的列表,所以 需要遍历【len(node)-2】次,即11次。
又因为 i+=2,所以遍历5次
反序列化的理论基础: 给所有节点从左到右从上到下依次从 1 开始编号。 那么已知一个节点的编号是 i, 那么其左子节点就是 2 * i, 右子节点就是 2 * 1 + 1, 父节点就是 (i + 1) / 2。
# 2.反序列化 def deserialize(self, data): if data == '#': return None nodes = data.split(',') # 通过 ',' 分隔每个元素,得到 11 个节点 root = TreeNode(nodes[0]) q = collections.deque([root]) i = 0 while q and i < len(nodes) - 2: cur = q.popleft() lv = nodes[i + 1] rv = nodes[i + 2] # print('cur =',cur.val,end='\t') # 这里打印的是val值,其实它指向的是地址 # print('lv =',lv,end='\t') # print('rv =',rv,end='\n') i += 2 if lv != '#': l = TreeNode(lv) q.append(l) cur.left = l if rv != '#': r = TreeNode(rv) q.append(r) cur.right = r return root'''作者:fe-lucifer链接:https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/solution/297-er-cha-shu-de-xu-lie-hua-yu-fan-xu-lie-hua-12/来源:力扣(LeetCode)著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。'''
有没有一点懵?
没事,继续看图 我们发现,queue的结束正好是循环的次数,反序列函数的优化 可参见【思路2】该方法的理论基础同思路1,不一样的之处如下:
class Codec: def serialize(self, root): if not root: return "[]" queue = collections.deque() queue.append(root) res = [] while queue: node = queue.popleft() if node: res.append(str(node.val)) queue.append(node.left) queue.append(node.right) else: res.append("null") return '[' + ','.join(res) + ']' def deserialize(self, data): if data == "[]": return vals, i = data[1:-1].split(','), 1 root = TreeNode(int(vals[0])) queue = collections.deque() queue.append(root) while queue: node = queue.popleft() if vals[i] != "null": node.left = TreeNode(int(vals[i])) queue.append(node.left) i += 1 if vals[i] != "null": node.right = TreeNode(int(vals[i])) queue.append(node.right) i += 1 return root'''作者:jyd链接:https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/solution/mian-shi-ti-37-xu-lie-hua-er-cha-shu-ceng-xu-bian-/来源:力扣(LeetCode)著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。'''
话不多说,看图
注:ans 是 str 类型
class Codec: # 1.反序列函数 def serialize(self, root): if not root: return '#' #print('这次root为=',root.val) ans = str(root.val) + "," + self.serialize(root.left) + "," +self.serialize(root.right) #print('返回ans=',ans) #print('\n') return ans # 2.反序列函数 def deserialize(self, data): data_list = data.split(',') print(data_list) def decoder(data_list): if len(data_list)<=0: return None data_val = data_list.pop(0) print('data_val = ',data_val) root = None if data_val != '#': # 为空(#)就跳过,非空就建立节点, print('此时data_list还剩 = ',data_list) print('\n') root = TreeNode(int(data_val)) root.left = decoder(data_list) root.right = decoder(data_list) return decoder(data_list)# 链接 https://blog.csdn.net/u010005281/article/details/79787278
显然,递归更快
~蟹蟹♪(・ω・)ノ支持 ~