题目:二叉树被记录成文章的过程叫做二叉树的序列化,通过文件的内容重建原来的二叉树的过程叫做二叉树的反序列化。给定一颗二叉树的头节点head,并已知二叉树的节点值的类型为32位整型。请设计一种二叉树序列化和反序列化的方案,并用代码实现。
解答:通过先序遍历实现序列化和反序列化
先介绍先序遍历下的序列化过程,首先假设序列化的结果字符串为str,初始化str="".先遍历二叉树,如果遍历到null节点,就在str的末尾加上“#!”,“#表示这个节点为空”,节点值不存在,“!”表示一个值的结束;如果遇到不为空的节点,假设这个值为3,就在str的末尾加上“3!”。比如如图所示的二叉树;
根据上文描述,先序遍历的序列化,最后的结果字符串str为:12!3!#!#!#!.
为什么会在每一个节点的后面都要加上感叹号,如果不加会有歧义,如下图所示,先序遍历str的字符串结果为:123###。所以不加感叹号说明生产的字符串并不代表唯一的树。
先序遍历序列化的全部过程如下:
public class Node{
public int value;
public Node left;
public Node right;
public Node(int data){
this.value = data;
}
}
public String serialByPre(Node head){
if(haed == null){
return "#!";
}
String res = head.value+"!";
res += serialByPre(head.left);
res +=serialByPre(head.right);
return res;
}
接下来结束如何通过先序遍历序列化的结果字符串str,重构二叉树的过程,即反序列化。
把结果字符串str变成字符串类型的数组,记为values,数组代表一颗二叉树先序遍历的节点顺序。例如str="12!3!#!#!#!",生成的values[12,3,#,#,#],然后用values[0..4]按照先序遍历整棵树。
1.遇到12,生成节点值为12的节点(head),然后用values[1..4]建立节点12的左子树。
2.遇到3,生成节点值为3的节点,它是节点12的左孩子,然后用values[2..4]建立节点3的左子树。
3.遇到#,生成null节点,它是节点3的左孩子,该节点为null,所以这个节点没有后续建立子树的过程。回到节点3后,用values[3..4]建立节点3的右子树。
4.遇到#,生成null节点,它是节点3的右孩子,该节点为null,所以这个节点没有后续建立子树的过程。回到节点3后,再回到节点1,用values[4],建立节点1的右子树。
5.遇到#,生成null节点,它是节点1的右孩子,该节点为null,所以这个节点没有后续建立子树的过程。整个过程结束。
具体代码如下所示:
public Node reconByPreString(String preStr){
String[] values = preStr.split("!");
Queue<String> queue = new LinkedList<String>();
for(int i=0;i != value.length;i++){
queue.offer(values[i]);
}
return reconPreOrder(queue);
}
public Node reconPreOrder(Queue<String> queue){
String value = queue.poll();
if(value.equals("#")){
reutrn null;
}
Node head = new Node(Integer.valueOf(value));
head.left = reconPreOrder(queue);
head.right = reconPreOrder(queue);
reutrn head;
}