题目描述
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
思路
题目说白了就是让你设计两个算法,一个是把二叉树转成字符串,一个是把字符串转成二叉树。
前序遍历比较适合序列化二叉树,先把根节点序列化到字符串里,然后再序列化它的左右子树。
但是,这两个算法转换前后要一一对应,不能有歧义,比如:
这两个图,如果按照前序遍历序列化,都会得到66666这个字符串,而反序列化的时候却无法还原回去,因为66666不止对应一种结构。
我们可以用别的字符来替代null结点,比如用’#‘的话,左边序列化就是666##6##6##,右边就是66##66##6##,这样就可以保证一一对应了。
当然还有一个要注意的地方,我们要用一个分隔符把结点之间隔开,不然我们不知道这个结点究竟是6,还是66,还是666…这里我采用’,'逗号。
先上代码,一些细节在下面解释。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if(root == null){
return "#";
}
String left = serialize(root.left);
String right = serialize(root.right);
return String.valueOf(root.val) + "," + left + "," + right;
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
String[] strs = data.split(",");
int[] i = {0};
return dfs(strs, i);
}
private TreeNode dfs(String[] strs, int[] i){
String str = strs[i[0]];
i[0]++;
if(str.equals("#")){
return null;
}
TreeNode node = new TreeNode(Integer.parseInt(str));
node.left = dfs(strs, i);
node.right = dfs(strs, i);
return node;
}
}
// Your Codec object will be instantiated and called as such:
// Codec ser = new Codec();
// Codec deser = new Codec();
// TreeNode ans = deser.deserialize(ser.serialize(root));
serialize实现了序列化,比较简单不做解释。
deserialize实现了反序列化,首先把序列化好的字符串以逗号分隔成一个数组,然后依次遍历这个数组,递归建树。
int[] i 表示当前遍历到的数组的下标,为什么不用int呢,因为int作为形参的话,在方法内部改变了值,只会在当前方法内部生效,所以无法提供给别的调用者了,所以采用int[]