题目:
请实现两个函数,分别用来序列化和反序列化二叉树
思路:
序列化主要就是在前后端交互时候需要转换下,毕竟网络传输的是流式数据(二进制或者文本),而不是对象。所以序列化二叉树就是转化成字符串。
之前解决重建二叉树问题时,我们可以知道,两个遍历序列就可以确定一颗二叉树。(比如前序遍历序列和中序遍历序列)。
受此启发,序列化时候我们可以生成一个前序遍历序列和一个中序遍历序列,在反序列化时通过这两个序列重构出原二叉树。
但这个思路有两个个缺点就是:
1.如果二叉树有数值重复的节点,那么必须区分谁是前序遍历序列,谁是后序遍历序列。
2.只有当两个序列所有数据读出后才能开始反序列化。
我们可以通过深度遍历或者广度遍历序列都行,当然我们最终选择了深度优先遍历,因为可以不用额外的空间。
此外还有个技巧就是为了更好地知道遍历某个子树的结束,也就是当我们遍历到null时,我们需要用换位符(比如$)代表,方便反序列化。
程序:
class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
public class subject61 {
public static String Serialize(TreeNode root) {//记录Null指针的前序遍历
if(root == null) {
return "$,";
}
StringBuffer str = new StringBuffer();
str.append(root.val + ",");
str.append(Serialize(root.left));
str.append(Serialize(root.right));
return str.toString();
}
public static TreeNode Deserialize(String str) {
StringBuffer strBuf = new StringBuffer(str);
return DeserializeCore(strBuf);
}
public static TreeNode DeserializeCore(StringBuffer reStr) {
if(reStr.length() == 0) {
return null;
}
String temp = reStr.substring(0, reStr.indexOf(","));
reStr.delete(0, reStr.indexOf(",") + 1);
if(temp.equals("$")) {
return null;
}
TreeNode node = new TreeNode(Integer.parseInt(temp));
node.left = DeserializeCore(reStr);
node.right = DeserializeCore(reStr);
return node;
}
public static void main(String args[]) {
// 1
// // \\
// 2 3
// // \\
// 4 5
// inorder->42513
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
String result = Serialize(root);
System.out.println(result);//1,2,4,$,$,5,$,$,3,$,$,
System.out.println(Deserialize(result));
}
}