题目
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
提示: 这与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。
说明: 不要使用类的成员 / 全局 / 静态变量来存储状态,你的序列化和反序列化算法应该是无状态的。
题目链接:link.
分析
做这道题要知道三个名词:二叉树、序列化、反序列化。题目中都有介绍,其实如果学习过数据结构,这道题应该不难。
这样想:每个二叉树可以分成三个部分,根节点、左子树、右子树,而左子树和右子树又可以当成一个二叉树。这思路是不是很熟悉?对的,就是递归。而根据递归访问的顺序不同,又可以分成先序,中序和后序遍历,这里的先中后是指根节点的访问是最开始还是中间或最后 。依此,我们就有了解题思路。
题解
准备
在本地进行程序测试时,首先要定义一些东西,比如节点的结构:
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
// 重写toString方法,这里也是递归
@Override
public String toString() {
return "TreeNode{" +
"val=" + val +
", left=" + left +
", right=" + right +
'}';
}
}
递归(先序遍历)
首先我们来看序列化,就是把树按照一定的方式以字符串输出出来,这里选择先序,中序后续就是把输出val调换位置,代码如下:
public static String serialize(TreeNode root) {
return serialize(root,"");
}
public static String serialize(TreeNode root, String str){
if(root == null) str += "None,";
else{
str += root.val+",";
str = serialize(root.left , str);
str = serialize(root.right , str);
}
return str;
}
反序列化,根据前面序列化的结果,将字符串反序列化成树,代码如下:
public static TreeNode deserialize(String data) {
String[] s = data.split(",");
List<String> l = new LinkedList<String>(Arrays.asList(s));
return deserialize(l);
}
public static TreeNode deserialize(List<String> l){
if(l.get(0).equals("None")){
l.remove(0);
return null;
}
TreeNode root = new TreeNode(Integer.parseInt(l.get(0))); // 初始化根节点
l.remove(0);
root.left = deserialize(l);
root.right = deserialize(l);
return root;
}
总结
如果系统学习过数据结构里的二叉树,这个题应该不算难,想清楚递归的方式。可以试着把中序和后序遍历的代码写出来。