首先说下什么是序列化、持久化。
其实就是写入到文件中,这样下次便于读取再次修改啥的。
那么那些牛客什么的OJ网站是怎么判断我们写的代码输出的树的结构是否正确呢?他们其实就是利用了树的序列化,把树的这种结构转换为字符串,这样的话就可以方便比较。我们不能直接拿节点的内存地址来存储把,所以我们需要建立一套规则,使得二叉树可以与字符串一一对应,根据一个二叉树可以唯一的得到一个字符串,根据一个字符串也可以唯一的还原出一棵二叉树。
序列化需要将每个结点按照一定的顺序转换为字符串,关键是这个顺序是什么顺序,这个顺序其实就是遍历树的顺序,按照遍历结点的顺序将结点转化为字符串即可,因此先序遍历、中序遍历、后序遍历、按层遍历都可以进行序列化。
这里我写了中序与层序遍历的序列化作为参考:
- “#”代表的是空节点 "!"代表了结尾
- 首先是节点的定义:
public static class Node{
public int value;
public Node left;
public Node right;
public Node(int value){
this.value = value;
}
}
- 中序遍历实现序列化:
//二叉树的序列化,按照先序的顺序,其实就是把二叉树转换成一个字符串
public static String serialByPre(Node head){
if(head == null){
return "#!";
}
String res = head.value + "!";
res += serialByPre(head.left);
res += serialByPre(head.right);
return res;
}
// 二叉树的反序列化
public static Node reconByPreString(String preStr){
String[] values = preStr.split("!");
Queue<String> queue = new LinkedList<>();
for (int i = 0; i < values.length; i++) {
queue.add(values[i]);
}
return reconPreOrder(queue);
}
//一个递归函数 恢复二叉树的结构
public static Node reconPreOrder(Queue<String> queue){
String cur = queue.poll();
if(cur.equals("#")){
return null;
}
Node head = new Node(Integer.valueOf(cur));
head.left = reconPreOrder(queue);
head.right = reconPreOrder(queue);
return head;
}
- 层序遍历实现序列化:
//序列化一个二叉树,使用层序遍历方式
public static String serialByLevel(Node head){
if(head == null){
return "#!";
}
String res = head.value + "!";
Queue<Node> queue = new LinkedList<>();
queue.add(head);
while (!queue.isEmpty()){
Node cur = queue.poll();
if(cur.left != null){
res += cur.left.value + "!";
queue.offer(cur.left);
}else {
res += "#!";
}
if(cur.right != null){
res += cur.right.value + "!";
queue.offer(cur.right);
}else{
res += "#!";
}
}
return res;
}
//非递归恢复二叉树的主函数
public static Node reconByLevelString(String levelStr){
String[] values = levelStr.split("!");
int index = 0;
Node head = generateNodeByString(values[index++]);
Queue<Node> queue = new LinkedList<>();
if(head != null){
queue.offer(head);
}
Node node = null;
while (!queue.isEmpty()){
node = queue.poll();
node.left = generateNodeByString(values[index++]);
node.right = generateNodeByString(values[index++]);
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
}
return head;
}
public static Node generateNodeByString (String val){
if(val.equals("#")){
return null;
}
return new Node(Integer.valueOf(val));
}