1. 序列化二叉树
(1)DFS
DFS遍历是从根节点开始,一直往左子节点走,当到达叶子节点的时候会返回到父节点,然后从从父节点的右子节点继续遍历
class Codec {
//把树转化为字符串(使用DFS遍历,也是前序遍历,顺序是:根节点→左子树→右子树)
public String serialize(TreeNode root) {
//边界判断,如果为空就返回一个字符串"#"
if (root == null)
return "#";
return root.val + "," + serialize(root.left) + "," + serialize(root.right);
}
//把字符串还原为二叉树
public TreeNode deserialize(String data) {
//把字符串data以逗号","拆分,拆分之后存储到队列中
Queue<String> queue = new LinkedList<>(Arrays.asList(data.split(",")));
return helper(queue);
}
private TreeNode helper(Queue<String> queue) {
//出队
String sVal = queue.poll();
//如果是"#"表示空节点
if ("#".equals(sVal))
return null;
//否则创建当前节点
TreeNode root = new TreeNode(Integer.valueOf(sVal));
//分别创建左子树和右子树
root.left = helper(queue);
root.right = helper(queue);
return root;
}
}
(2)BFS
一层一层从往下遍历
public class Codec {
//把树转化为字符串(使用BFS遍历)
public String serialize(TreeNode root) {
//边界判断,如果为空就返回一个字符串"#"
if (root == null)
return "#";
//创建一个队列
Queue<TreeNode> queue = new LinkedList<>();
StringBuilder res = new StringBuilder();
//把根节点加入到队列中
queue.add(root);
while (!queue.isEmpty()) {
//节点出队
TreeNode node = queue.poll();
//如果节点为空,添加一个字符"#"作为空的节点
if (node == null) {
res.append("#,");
continue;
}
//如果节点不为空,把当前节点的值加入到字符串中,
//注意节点之间都是以逗号","分隔的,在下面把字符
//串还原二叉树的时候也是以逗号","把字符串进行拆分
res.append(node.val + ",");
//左子节点加入到队列中(左子节点有可能为空)
queue.add(node.left);
//右子节点加入到队列中(右子节点有可能为空)
queue.add(node.right);
}
return res.toString();
}
//把字符串还原为二叉树
public TreeNode deserialize(String data) {
//如果是"#",就表示一个空的节点
if (data == "#")
return null;
Queue<TreeNode> queue = new LinkedList<>();
//因为上面每个节点之间是以逗号","分隔的,所以这里
//也要以逗号","来进行拆分
String[] values = data.split(",");
//上面使用的是BFS,所以第一个值就是根节点的值,这里创建根节点
TreeNode root = new TreeNode(Integer.parseInt(values[0]));
queue.add(root);
for (int i = 1; i < values.length; i++) {
//队列中节点出栈
TreeNode parent = queue.poll();
//因为在BFS中左右子节点是成对出现的,所以这里挨着的两个值一个是
//左子节点的值一个是右子节点的值,当前值如果是"#"就表示这个子节点
//是空的,如果不是"#"就表示不是空的
if (!"#".equals(values[i])) {
TreeNode left = new TreeNode(Integer.parseInt(values[i]));
parent.left = left;
queue.add(left);
}
//上面如果不为空就是左子节点的值,这里是右子节点的值,注意这里有个i++,
if (!"#".equals(values[++i])) {
TreeNode right = new TreeNode(Integer.parseInt(values[i]));
parent.right = right;
queue.add(right);
}
}
return root;
}
}
2. 序列化二叉搜索树
(1)遍历
二叉树结构是一个二维平面内的结构,而序列化出来的字符串是一个线性的一维结构。所谓的序列化就是把结构化的数据 “打平”,其实就是在考察二叉树的遍历方式。
对于二叉树来说需要中序遍历结果与前序或后序结果结合才能构建出来,而二叉搜索树根据特性(右子树 > 根 > 左子树)只需要前序或后序遍历结果就可以构建出来。
前序遍历:根 - 左 - 右。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Codec {
public String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
serialize(root, sb);
return sb.toString();
}
//序列化二叉搜索树
private void serialize(TreeNode root, StringBuilder sb) {
if (root == null) {
sb.append("N").append(",");
return ;
}
sb.append(root.val).append(",");
serialize(root.left, sb);
serialize(root.right, sb);
}
//反序列化二叉搜索树
public TreeNode deserialize(String data) {
LinkedList<String> nodes = new LinkedList<>();
for (String s : data.split(",")) nodes.add(s);
return deserialize(nodes);
}
private TreeNode deserialize(LinkedList<String> nodes) {
if (nodes.isEmpty()) return null;
String first = nodes.removeFirst();
if (first.equals("N")) return null;
TreeNode root = new TreeNode(Integer.parseInt(first));
root.left = deserialize(nodes);
root.right = deserialize(nodes);
return root;
}
}