题目描述
请实现两个函数,分别用来序列化和反序列化二叉树
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
例如,我们可以把一个只有根节点为1的二叉树序列化为"1,",然后通过自己的函数来解析回这个二叉树
解题思路:
两种思路:一种是使用先序遍历,另一种是宽度优先搜索,即按照层次进行二叉树的序列化与反序列化。
对于序列化而言,是有很多细节在里面的。在先序遍历的过程中,当访问到节点为空,返回“#!”(作为递归的终止条件)。之后将当前节点的数值添加到StringBuilder对象中,最后递归左右子节点。StringBuilder helpSerialize(TreeNode root, StringBuilder s),这里看一下返回值类型是StringBuilder,因为最终还要返回给原始函数。
因此在遇到空节点,也即遇到终止条件时,可以通过append函数添加“#!”,之后返回StringBuilder对象;也可以通过在递归函数体中直接判断左右子树是否为null来添加“#!”,那么这种情况下,在遇到终止条件后,就不需要再添加“#!”,直接返回StringBuilder对象即可。
对于反序列化而言,需要定义一个全局变量来指向字符串,可以通过split函数将字符串序列进行预处理(这种情况,传递的参数就是字符串数组,并且不包括“!”),在遇到“#”字符时,游标++,返回空即可。然后建立二叉树的相应节点,游标++,并且令当前节点的左右子节点分别指向后续字符串数组的递归回溯结果;或者将字符串直接作为参数传递过去,使用charAt函数获取每个字符(这种情况下,在当前字符为"#"时,游标需要+=2,因为需要越过"#!"两个字符。另,通过while循环获取每个节点的数值),剩下的操作都是大同小异了。代码如下:
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public int cur = 0 ;
String Serialize(TreeNode root) {
if(root == null) return "" ;
return helpSerialize(root,new StringBuilder()).toString() ;
//if(root == null) return "#!" ;
//return root.val + "!" + Serialize(root.left) + Serialize(root.right);
}
StringBuilder helpSerialize(TreeNode root, StringBuilder s) {
if(root == null) {
s.append("#!") ;
return s ;
}
s.append(String.valueOf(root.val)).append("!") ;
helpSerialize(root.left,s) ;
helpSerialize(root.right,s) ;
return s ;
}
TreeNode Deserialize(String str) {
if(str.length() == 0) return null ;
return helpDeserialize(str) ;
}
TreeNode helpDeserialize(String str) {
if(str.charAt(cur) == '#') {
cur += 2 ;
return null ;
}
int sum = 0 ;
while(str.charAt(cur) != '!') {
sum = sum*10+(str.charAt(cur)-'0') ;
++cur ;
}
++cur ;
TreeNode root = new TreeNode(sum) ;
root.left = helpDeserialize(str) ;
root.right = helpDeserialize(str) ;
return root ;
}
}
宽度优先搜索的方法,即按层处理,代码如下:
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
import java.util.Queue ;
import java.util.LinkedList ;
public class Solution {
public int cur = 0 ;
String Serialize(TreeNode root) {
if(root == null) return "" ;
Queue<TreeNode> queue = new LinkedList<TreeNode>() ;
queue.offer(root) ;
StringBuilder ans = new StringBuilder("") ;
ans.append(root.val).append("!") ;
while(!queue.isEmpty()) {
TreeNode temp = queue.poll() ;
if(temp.left == null) {
ans.append("#!") ;
} else {
ans.append(temp.left.val+"").append("!") ;
queue.offer(temp.left) ;
}
if(temp.right == null) {
ans.append("#!") ;
} else {
ans.append(temp.right.val+"").append("!") ;
queue.offer(temp.right) ;
}
}
return ans.toString() ;
}
TreeNode Deserialize(String str) {
if(str.length() == 0) return null ;
Queue<TreeNode> queue = new LinkedList<TreeNode>() ;
String[] s = str.split("!") ;
TreeNode root = new TreeNode(Integer.valueOf(s[0])) ;
int index = 1;
int len = s.length ;
queue.offer(root) ;
while(!queue.isEmpty() && index < len) {
TreeNode tmp = queue.poll() ;
if(!s[index].equals("#")) {
TreeNode node = new TreeNode(Integer.parseInt(s[index])) ;
tmp.left = node ;
queue.offer(node) ;
++index ;
} else ++index ;
if(index < len && !s[index].equals("#")) {
TreeNode node1 = new TreeNode(Integer.parseInt(s[index])) ;
tmp.right = node1 ;
queue.offer(node1) ;
++index ;
} else ++index ;
}
return root ;
}
}