面试题37:序列化二叉树
题目:请实现两个函数,分别用来序列化和反序列化二叉树
思路:
- 因为从前序遍历序列和中序遍历序列中可以恢复出一棵二叉树,所以不难想到把一棵二叉树序列化成一个前序遍历序列和一个中序遍历序列。然后在反序列化时通过这两个序列重构出原二叉树。但是这样做有两个缺点:①该方法要求二叉树中不能有数值重复的节点;②只有当两个序列中所有数据都读出后才能开始反序列化。如果两个遍历序列的数据是从一个流中读出来的,那么可能需要等待较长的时间。
- 实际上,如果二叉树的序列化是从根节点开始的,那么相应的反序列化在根节点的数值读出来以后就可以开始了。因此,我们可以根据前序遍历的顺序来序列化二叉树,在碰到 null 值的节点时,这些 null 节点我们用一个特殊的符号来代替,比如说"$"。另外,节点的数值之间要用一个特殊的符号,比如说 “,”。
代码实现:
package Question37;
import com.sun.source.tree.Tree;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.Queue;
public class T01 {
public static String preSeq = "";
public static void main(String[] args) {
TreeNode node1 = new TreeNode(1);
TreeNode node2 = new TreeNode(2);
TreeNode node3 = new TreeNode(3);
TreeNode node4 = new TreeNode(4);
TreeNode node5 = new TreeNode(5);
node1.left = node2;
node1.right = node3;
node3.left = node4;
node3.right = node5;
Serialize(node1);
System.out.println(preSeq);
TreeNode root = Deserialize(preSeq);
System.out.println("123");
}
public static String Serialize(TreeNode root) {
if(root != null) {
preSeq += "" + root.value + ",";
Serialize(root.left);
Serialize(root.right);
} else {
preSeq += "$,";
}
return preSeq;
}
public static TreeNode Deserialize(String data) {
if(data == null || data.length() == 0) return null;
Queue<String> queue = new LinkedList<>();
for(String str : data.split(","))
queue.offer(str);
return help(queue);
}
public static TreeNode help(Queue<String> queue) {
if(queue.isEmpty()) return null;
String str = queue.poll();
if(!str.equals("$")) {
int number = Integer.parseInt(str);
TreeNode root = new TreeNode(number);
root.left = help(queue);
root.right = help(queue);
return root;
} else {
return null;
}
}
}
class TreeNode {
int value;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.value = val;
}
}