Binary Tree二叉树笔记④--序列化篇
前言
在上一期我们对二叉树的构造进行了深入的了解,重点掌握了构造的核心原理以及一些细节上面的问题。下面来学习二叉树的序列化,通过本篇文章你可以学会以下的题目
Leetcode
297.二叉树的序列化与反序列化
二叉树的序列化与反序列化
该题目本质上,就是把二叉树转换为字符串,再从字符串转为二叉树的过程。
至于我们序列化的过程,使用什么符号定义并不重要,只要最后能够反序列化出来即可。
eg
对于一颗这样的树,我们可以将他序列化成2,1,#,6,3,#,#
其实他考察的就是如何对二叉树进行遍历。
二叉树的递归遍历有三种,前序中序后序,迭代遍历有层序,那么就从层序开始,看如何解题
前序遍历解法
我们知道,前序遍历的代码就是在递归之前写的,那么就有以下的逻辑1
2
3if(!root)return '#';
traverse(root.left);
traverse(root.right);
那么我们就很容易得出序列化的过程了,就是字符串的连接1
2
3
4var serialize = function (root) {
if(!root)return '#';
return `${root},${serialize(root.left)},${serialize(root.right)}`;
}
反序列化
那么其实反序列化,就是把序列化的这一串字符串转换为treenode。
对于一个字符串来说,js提供了split方法帮我们进行分割,也就是说以下的逻辑,会分割出一个数组1
const nodeArr = data.split(",");
我们拿到了这个数组,因为他是前序的序列化而来的,那么我们根据前序的特性可以得到以下条件
第一个值是根,这就是我们的递归关键,回想一下前序构造二叉树,我们可以得到如下的代码1
2
3
4
5
6
7
8const build = (preorder)=>{
const val = preorder.shift();
if(val === '#')return null;
const root = new TreeNode(val);
root.left = build(preorder);
root.right = build(preorder);
return root;
}
那么我们的反序列化就能写出来了1
2
3
4
5
6
7
8
9
10
11
12
13var deserialize = function (data) {
const nodearr = data.split(",");
if (!nodearr.length) return null;
const build = (nodearr) => {
const val = nodearr.shift();
if (val === '#') return null;
const root = new TreeNode(val);
root.left = build(nodearr);
root.right = build(nodearr);
return root;
}
return build(nodearr);
};
完整代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22var serialize = function (root) {
if (!root) {
return '#'
}
return `${root.val},${serialize(root.left)},${serialize(root.right)}`
};
var deserialize = function (data) {
const nodearr = data.split(",");
if (!nodearr.length) return null;
const build = (nodearr) => {
const val = nodearr.shift();
if (val === '#') return null;
const root = new TreeNode(val);
root.left = build(nodearr);
root.right = build(nodearr);
return root;
}
return build(nodearr);
};
总结
序列化就是转字符串的过程,这个过程用什么符号代替并不重要,只要最后能解析即可。一般是利用前序空节点返回#然后模板字符串拼接根+递归的左右
反序列化的就是解析字符串重构树的过程,注意需要用split分割字符串为数组,遇到#就返回null。
重构树的过程,由于他是数组转树,我们递归的时候就要注意递归的是数组,我们取节点就应该使用shift