思路:
序列化就是将二叉树变成字符串,可以在不同的编程语言系统中传递
反序列化就是将序列化的字符串重新构建成二叉树数据结构
为了确定唯一的二叉树,不可以用中序遍历结果,因为根节点在数组中间,无法确认根节点的位置
如果是前序遍历的话,根节点就是第一个元素
我们可以用前序遍历的特点来序列化二叉树
既然我们用前序遍历的方式来进行序列化,那么我们反序列化时也需要用同样的方式来进行反序列化
对了,我们知道,遍历分两种,层序遍历和递归遍历
这里我们使用递归前序遍历
序列化
先定义一个数组res,来储存每个节点的值,最后我们把元素拼接起来
每次前序遍历到一个节点时,判断是不是空节点
如果是空节点,我们在res中追加一个特殊字符,可以用"#","null",这里用的null
不是空节点的话, 在res中追加这个节点的值,并且递归它的左右子树
最后用join(",")来拼接成字符串
反序列化
我们拿到的是二叉树序列化的结果,是个字符串
我们可以用split(",")分割成数组values
然后我们遍历这个数组,但是我们要用递归的方式,因为我们是从前往后遍历的
为了实现对数组的遍历,我们必须维护一个递增的索引index
然后在递归函数里面,前序的位置进行判断,是否为"null"
如果是,说明这是一个空节点,我们直接返回null
不是的话,我们构建一个新节点,值就是values[index]
注意,不管是不是空节点,每遍历一个数组元素,就给index++
然后把当前节点的左右子树构建出来,使用dfs
返回当前节点
/**
* Encodes a tree to a single string.
*
* @param {TreeNode} root
* @return {string}
*/
var serialize = function (root) {
//数组
let res = [];
//递归函数
function dfs(root) {
//如果节点是空节点
if (!root) {
res.push("null");
return;
} else {
res.push(root.val);
dfs(root.left);
dfs(root.right);
}
}
dfs(root);
return res.join(",");//返回字符串
};
/**
* Decodes your encoded data to tree.
*
* @param {string} data
* @return {TreeNode}
*/
var deserialize = function (data) {
//非空判断
if (!data) return null;
//序列化数组
const values = data.split(",");
//遍历这个序列化数组
let index = 0;//维护索引
function dfs() {
const val = values[index];
index++;
if (val === "null") return null;
//不是空节点
//构建根节点
const root = new TreeNode(Number(val));
//递归左右子树
root.left = dfs();
root.right = dfs();
//返回当前节点
return root;
}
return dfs();
};