题目描述
请实现两个函数,分别用来序列化和反序列化二叉树
把对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为对象的过程称为对象的反序列化。
思路:
重建二叉树我们知道可以通过前序遍历序列和中序遍历序列构造出一个新的二叉树来,因此,我们可以将一个二叉树序列化为一个前序 遍历序列和一个中序遍历序列,然后反序列化时通过这两个二序列重构出原二叉树。
该思路有两个缺点:
1.该方法要求二叉树不能有重复数值的节点;
2.只有当两个序列中所有的数据全都读出后才能开始反序列化。而如果两个遍历的序列是从数据流中读出的,则需要等待很长的时间。
实际上,如果二叉树序列化是从根节点开始的,则相应的反序列化在根节点的数值读出来时就已经开始了。因此我们可以根据前序遍历的顺序来序列化二叉树。
前序遍历上图的二叉树,得到的结果是1,2,4,$,$,$,3,5,$,$,6,$,$。分析这个序列,第一个读出的是1,因为前序遍历是从根节点开始的,所以根节点的值为1,接下来是2,所以2是1的左子节点,依次,4是2的左子节点,接着读出$,$,说明值为4的节点,左右节点都为null,4为该二叉树的叶子节点。接下来回到2,重建它的右节点,因为读出的是$,所以2的右节点为空,回到1,构建它的右节点,为3,读出5,5是3的左子节点,读出$,$,所以5的左右子节点为空,回到3,构建3的右节点,6是其右节点,读出$$,所以6的左右子节点为空,6为叶子节点。
总结前面序列化和反序列化的过程,我们发现二叉树分解为3部分:根节点,左子树,右子树,我们在处理(序列化,反序列化)它的根节点之后再处理它的左右子树。这是典型的把问题递归分解然后逐个解决的过程。
实现1:
1.序列化是指通过前序遍历把二叉树变成数组
2.反序列化是指重建二叉树
前序遍历序列化,null序列化为‘#’,index 为全局变量
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
//定义全局变量index
public int index=-1;
String Serialize(TreeNode root) {
StringBuffer sb=new StringBuffer();
if(root==null){
sb.append("#,");
return sb.toString();
}
sb.append(root.val+",");
sb.append(Serialize(root.left));
sb.append(Serialize(root.right));
return sb.toString();
}
TreeNode Deserialize(String str) {
if(str==null){
return null;
}
String[] strs=str.split(",");
return DeserializeStr(strs);
}
private TreeNode DeserializeStr(String[] strs){
index++;
TreeNode node=null;
if(!strs[index].equals("#")){
node=new TreeNode(Integer.valueOf(strs[index]));
node.left=DeserializeStr(strs);
node.right=DeserializeStr(strs);
}
return node;
}
}