1. 问题描述:
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
提示: 输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。
示例 1:
输入:root = [1,2,3,null,null,4,5]
输出:[1,2,3,null,null,4,5]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
示例 4:
输入:root = [1,2]
输出:[1,2]
提示:
- 树中结点数在范围
[0, 104]
内 -1000 <= Node.val <= 1000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree
2. 思路分析:
对于二叉树的序列化我们可以使用深度优先搜索来确定序列化的结果,声明一个全局字符串变量path来记录二叉树递归过程的路径,在前序遍历的过程中添加二叉树节点的值到路径path中,当递归到空节点的时候添加字符"#",添加这个字符的目的是为了在二叉树的反序列化操作中通过二叉树的前序遍历确定具体的二叉树(只有前序遍历是无法确定一棵具体的二叉树的,通过字符#则可以确定父子节点之间的关系),通过字符#就可以知道父节点的某个孩子为空,并且需要声明一个全局变量index来记录当前反序列化二叉树递归路径path的位置,这样在递归返回到上一层的时候才可以同步更新当前递归的path的位置,如果不是全局变量的话那么可能递归到第二层节点的时候就不会往下创建其他的子树了,因为往下递归的过程中对应的路径字符串path的位置是没有进行同步更新的。
3. 代码如下
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Codec:
path = ""
# 声明一个全局变量这样可以进行同步更新
index = 0
# 序列化
def dfs_s(self, root: TreeNode):
# 当节点为空的时候那么加上"#", 通过这个符号就可以构造出对应的二叉树
if not root:
self.path += "#,"
return
self.path += str(root.val) + ","
self.dfs_s(root.left)
self.dfs_s(root.right)
def serialize(self, root):
# 使用深搜的方式来序列化二叉树
self.dfs_s(root)
return self.path
# 反序列化
def dfs_d(self, data: str):
if data[self.index] == "#":
self.index += 2
return None
k = self.index
while data[self.index] != ",":
self.index += 1
# 注意下标的转换
root = TreeNode(int(data[k: self.index]))
self.index += 1
root.left = self.dfs_d(data)
root.right = self.dfs_d(data)
return root
def deserialize(self, data):
return self.dfs_d(data)
# 前序遍历
def preOrder(self, root: TreeNode):
if not root: return
print(root.val)
self.preOrder(root.left)
self.preOrder(root.right)
# if __name__ == '__main__':
# root = TreeNode(1)
# l = TreeNode(2)
# r = TreeNode(3)
# rl = TreeNode(4)
# rr = TreeNode(5)
# root.left = l
# root.right = r
# r.left = rl
# r.right = rr
# print(Codec().serialize(root))
# root = Codec().deserialize("1,2,#,#,3,4,#,#,5,#,#,")
# Codec().preOrder(root)