假设有一个二叉树
_30_ / \ 10 20 / / \ 50 45 35
解法一:
前序遍历二叉树,空节点处插入#。如图
_30_ / \ 10 20 / \ / \ 50 # 45 35 /\ /\ /\ # # # # # #序列为:30,10,50,#,#,#,20,45,#,#,35,#,#
反序列化时只需要按照前序遍历的顺序,从序列中取节点,生成二叉树即可。
//序列化
public String Serialize(TreeNode root) {
StringBuffer result = new StringBuffer();
Serialize2(root, result);
result.deleteCharAt(result.length() - 1);
return result.toString();
}
private void Serialize2(TreeNode root, StringBuffer result) {
if (root == null) {
result.append('#');
result.append(',');
return;
}
result.append(root.val);
result.append(',');
Serialize2(root.left, result);
Serialize2(root.right, result);
}
//反序列化
public TreeNode Deserialize(String str) {
String[] res = str.split(",");
TreeNode root = Deserialize2(res);
return root;
}
//代表当前序列序号,为全局变量
int i = 0;
private TreeNode Deserialize2(String[] res) {
if (res[i].equals("#")) {
i++;
return null;
}
TreeNode root = new TreeNode(Integer.valueOf(res[i]));
i++;
root.left = Deserialize2(res);
root.right = Deserialize2(res);
return root;
}
利用队列,层次遍历二叉树生成序列。填充#后图与解法一相同:
_30_ / \ 10 20 / \ / \ 50 # 45 35 /\ /\ /\ # # # # # #
序列为:30,10,20,50,#,45,35,#,#,#,#,#,#
反序列化时只需要,建立队列按照层次遍历的顺序,从序列中取节点,生成二叉树。
//序列化
public String Serialize(TreeNode root) {
if(root == null) return null;
StringBuffer result = new StringBuffer();
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode tmp = queue.poll();
if (tmp == null) {
result.append("#,");
} else {
result.append(tmp.val + ",");
queue.add(tmp.left);
queue.add(tmp.right);
}
}
result.deleteCharAt(result.length() - 1);
return result.toString();
}
//反序列化
public static TreeNode Deserialize(String str) {
if (str == null || str.length() == 0)
return null;
String[] seq = str.split(",");
int index = 0;
TreeNode root = new TreeNode(Integer.valueOf(seq[index++]));
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode p = queue.poll();
if (!seq[index].equals("#")) {
TreeNode lc = new TreeNode(Integer.valueOf(seq[index]));
p.left = lc;
queue.add(lc);
}
index++;
if (!seq[index].equals("#")) {
TreeNode rc = new TreeNode(Integer.valueOf(seq[index]));
p.right = rc;
queue.add(rc);
}
index++;
}
return root;
}
解法三:
层次遍历二叉树,将二叉树填充成完全二叉树。
_30_ / \ 10 20 / \ / \ 50 # 45 35 /\ /\ /\ /\ # # # # # # # #序列为:30,10,20,50,#,45,35,#,#,#,#,#,#,#,#
反序列化时,利用完全二叉树性质。n号节点的左孩子为2*n+1,右孩子为2*n+2.
//序列化
public String Serialize2(TreeNode root) {
if(root == null){
return null;
}
StringBuffer sb = new StringBuffer();
Queue<TreeNode> queue = new LinkedList<>();
//用于记录非空节点的个数
int valNum = 1;
queue.add(root);
while(!queue.isEmpty()){
TreeNode tmp = queue.poll();
if(tmp != null){
valNum--;
sb.append(tmp.val + ",");
queue.add(tmp.left);
if(tmp.left != null) valNum++;
queue.add(tmp.right);
if(tmp.right != null) valNum++;
}else{
sb.append("#,");
//当后续队列中仍有非空节点,则需要其左右孩子继续填充#
if(valNum > 0){
queue.add(null);
queue.add(null);
}
}
}
sb.deleteCharAt(sb.length()-1);
return sb.toString();
}
//反序列化
public TreeNode Deserialize(String str) {
if(str == null || str.length() == 0){
return null;
}
return Deserialize(str.split(","), 0);
}
public TreeNode Deserialize(String[] strings, int index){
TreeNode tmp = null;
if(index < strings.length && !strings[index].equals("#")){
if(strings[index] != null){
tmp = new TreeNode(Integer.valueOf(strings[index]));
tmp.left = Deserialize(strings, index * 2 + 1);
tmp.right = Deserialize(strings, index * 2 + 2);
}
}
return tmp;
}