请实现两个函数,分别用来序列化和反序列化二叉树
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
例如,我们可以把一个只有根节点为1的二叉树序列化为"1,",然后通过自己的函数来解析回这个二叉树。
背景知识:
1,了解 String 和 StringBuilder() 的使用方法,以及二者之间的关系,如何互相转换。
参考:
Java的StringBuilder类_曹木匠-博客_java stringbuilder
String内容是不可变的,StringBuilder内容是可变的
StringBuilder处理字符串性能比String好
// string转换成StringBuilder
String str = "hello";
StringBuilder sb = new StringBuilder(str);
System.out.println(sb); // hello
// StringBuilder转换成String
String s = sb.toString();
System.out.println(s); // hello
2, 了解 String[] 字符串数组 与 字符串的关系, 如何转换。
public static String[] str2StrArray(String str,String splitRegex){
if(isEmpty(str)){
return null;
}
return str.split(splitRegex);
}
3, 了解Java中的 valueof()使用方法, 去除字符串数组中的值, 用于构造根节点。
https://www.runoob.com/java/number-valueof.html
Integer valueOf(String s):返回保存指定的 String 的值的 Integer 对象。
https://www.runoob.com/java/number-parseint.html
static int parseInt(String s)
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
String Serialize(TreeNode root) {
if(root == null) return "";
// 利用 StringBuilder构建一个可变的字符串对象,用于存放遍历二叉树的节点值
StringBuilder sb = new StringBuilder();
subSerialize(root, sb);
// String内容是不可变的,StringBuilder内容是可变的,所以将StringBuilder对象转换成字符串
return sb.toString();
}
StringBuilder subSerialize(TreeNode root, StringBuilder s) {
if(root == null) return s;
s.append(root.val).append("!");
if(root.left != null) {
subSerialize(root.left, s);
}else {
s.append("#!");
}
if(root.right != null) {
subSerialize(root.right, s);
}else {
s.append("#!");
}
return s;
}
int index = 0;
TreeNode Deserialize(String str) {
if(str == null || str.length() == 0) return null;
String[] sb = str.split("!");
return subDeserialize(sb);
}
TreeNode subDeserialize(String[] strings) {
if(strings[index].equals("#")) {
index++; // 注意,此处index需要移动到下一位,对下一位进行判定
return null;
}
// 构造完根节点 移动字符串数组的下标,准备构建根节点的左右子树
TreeNode root = new TreeNode(Integer.valueOf(strings[index]));
index++;
root.left = subDeserialize(strings);
root.right = subDeserialize(strings);
return root;
}
}
难点:
1, 辅助函数的构建
2,边界条件的考虑
3, 拓展, 关于中序/后序/层次遍历的 序列化,反序列化如何做? (注意, 中序可以序列化,但不可反序列化。 原因在于无法确定根节点的值。)