《剑指Offer》Java刷题 NO.61 序列化二叉树(二叉树,序列化(遍历),反序列化(构造),前序、层序遍历)
传送门:《剑指Offer刷题总目录》
时间:2020-07-16
题目:
请实现两个函数,分别用来序列化和反序列化二叉树
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过某种符号表示空节点(#),以 !表示一个结点值的结束(value!)。
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
思路:考察二叉树的遍历和构造二叉树
大致题意就是,例如对于一颗结点为0-6的满二叉树,先序遍历,序列化之后应该是:
0!1!3!#!#!4!#!#!2!5!#!#!6!#!#!
前中后序遍历、层序遍历都很简单,序列化的话用一个StringBuilder
就好了,这个地方复杂的是反序列化,需要维持一个index
去取对应位置的value
Java代码:
import java.util.LinkedList;
import java.util.Queue;
/**
* @author LiMin
* @Title: SerializeTree
* @Description: 请实现两个函数,分别用来序列化和反序列化二叉树
* @date 2020/7/16 15:00
*/
public class SerializeTree {
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);
TreeNode node6 = new TreeNode(6);
TreeNode node7 = new TreeNode(7);
node1.left = node2;
node1.right = node3;
node2.left = node4;
node4.right = node5;
node3.left = node6;
node5.right = node7;
SerializeTree serial = new SerializeTree();
String str = serial.serialBFS(node1);
TreeNode node0 = serial.deserialBFS(str);
System.out.println(node0.val);
}
/**
* 前序遍历序列化
*/
public String serialPreOrder(TreeNode pRoot) {
if (pRoot == null) {
return null;
}
StringBuilder builder = new StringBuilder();
preStrBuild(pRoot, builder);
return builder.toString();
}
private void preStrBuild(TreeNode pRoot, StringBuilder builder) {
if (pRoot == null) {
builder.append("#!");
return;
}
builder.append(pRoot.val + "!");
preStrBuild(pRoot.left, builder);
preStrBuild(pRoot.right, builder);
}
/**
* 前序遍历反序列化
*/
public TreeNode deserialPreOrder(String str) {
if (str == null || str.length() == 0) {
return null;
}
String[] strings = str.split("!");
return preTreeBuild(strings);
}
private int index = 0;
private TreeNode preTreeBuild(String[] strings) {
TreeNode root = null;
if (strings[index].equals("#")) {
index++;
return root;//"#"直接将结点返回,没有左右子结点
}//equal比较字符串内容
root = new TreeNode(Integer.parseInt(strings[index]));
index++;//每用掉一个string,index就向前走一步
root.left = preTreeBuild(strings);
root.right = preTreeBuild(strings);
return root;
}
/**
* 层序遍历序列化
*/
public String serialBFS(TreeNode pRoot) {
if (pRoot == null) {
return null;
}
StringBuilder builder = new StringBuilder();
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(pRoot);
while (!queue.isEmpty()) {
//null也放进队列
TreeNode cur = queue.poll();
if (cur == null) {
builder.append("#!");
continue;
}
builder.append(cur.val + "!");
queue.offer(cur.left);
queue.offer(cur.right);
}
return builder.toString();
}
/**
* 层序遍历反序列化
*/
public TreeNode deserialBFS(String str) {
if (str == null || str.length() == 0) {
return null;
}
String[] strings = str.split("!");
int idx = 0;
Queue<TreeNode> queue = new LinkedList<>();
TreeNode head = new TreeNode(Integer.parseInt(strings[idx++]));
queue.offer(head);
while (!queue.isEmpty()) {
TreeNode cur = queue.poll();
if (!strings[idx].equals("#")) {
cur.left = new TreeNode(Integer.parseInt(strings[idx++]));
queue.offer(cur.left);
} else {
idx++;//null结点不用再放进队列了,后面没有子树了;cur.left本来就是null
}
if (!strings[idx].equals("#")) {
cur.right = new TreeNode(Integer.parseInt(strings[idx++]));
queue.offer(cur.right);
} else {
idx++;//null结点不用再放进队列了,后面没有子树了;cur.right本来就是null
}
}
return head;
}
}