题目依旧来自《剑指Offer》和牛客网在线编程。
【题目】实现两个函数,分别实现序列化与反序列化二叉树。
/*
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) {
}
TreeNode Deserialize(String str) {
}
}
【分析1】首先明确序列化与反序列化二叉树。所谓的序列化二叉树就是按照树的某种遍历方式遍历二叉树,将每个结点的值以某种特殊符号(例如,)分隔保存到一个字符串中,如果结点为空,则使用另外一种特殊符号(例如#)表示。反序列化的意思就是根据序列化的字符串重构出该二叉树。这里需要特别说明一点的是,遍历到叶子结点后,还需要继续向下遍历,结点为空,则用特殊字符(例如#)表示。
【分析2】对于二叉树的遍历方式选择上,原则上前、中、后和层次遍历都是可以的。但是为了能够很容易的获取二叉树的根结点,因此我们可以选择前序遍历顺序,这样遍历出来的第一个元素就是二叉树的根结点对应的值。
【分析3】对于二叉树的序列化来说,现在就变成了一个前序遍历二叉树的过程。如果当前结点不为空,则将当前结点对应的值加入到字符串中;如果当前结点为空,则将特殊字符(例如,#)加入到字符串中。
【分析4】根据前序序列化的二叉树字符串,我们需要重构该二叉树。根据前序遍历的特点,我们在获取根结点后,首先应该一直向左构建左子树,直到遇到空结点。如果当前结点为空,则应该返回到它的父结点,然后构造它的父结点的右子树。以此类推,显然这也是一个递归进行的过程。
【代码】
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public int index = -1;
String Serialize(TreeNode root) {
StringBuilder builder = new StringBuilder();
pre(root,builder);
return builder.toString();
}
TreeNode Deserialize(String str) {
/*String[] array = str.split("!");
TreeNode root = null;
if("#".equals(array[0]))
return root;
else{
root.val = Integer.valueOf(array[0]);
TreeNode p = root;
TreeNode q = root;
int flag = 1
for(int i = 1;i < array.length;++i){
if("#".equals(array[i] && "#".equals(array[i+1]){
q = p;
}else {
TreeNode temp;
temp.val = Integer.valueOf(array[i]);
q.left = temp;
p = q;
q = temp;
}
}
}
return root;*/
index++;
String[] DLRseq = str.split(",");
TreeNode leave = null;
if(!DLRseq[index].equals("#")){
leave = new TreeNode(Integer.valueOf(DLRseq[index]));
leave.left = Deserialize(str);
leave.right = Deserialize(str);
}
return leave;
}
void pre(TreeNode root,StringBuilder builder){
if(root == null){
builder.append("#,");
}else{
builder.append(root.val+",");
pre(root.left,builder);
pre(root.right,builder);
}
}
}