题目描述
请实现两个函数,分别用来序列化和反序列化二叉树。
序列化二叉树
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串
,从而使得内存中建立起来的二叉树可以持久保存。
序列化可以基于先序
、中序
、后序
、按层
的二叉树遍历方式来进行修改。原理都是一样的(即遍历顺序不同而已,对每个结点的处理都是一样的),序列化的结果是一个字符串,序列化时通过某种符号表示空节点(#
),以 !
表示一个结点值的结束(value!
)。
这里以先序遍历的方式进行序列化举例:
先序序列化二叉树定义一个StringBuilder保存序列过程中的结果:按照先序遍历方式遍历二叉树,若结点非空则把"结点值!"
append到builder中;若结点空则把"#!"
append到builder中;最后用builder生成字符串就是序列化结果。
1. 递归写法
//使用递归先序遍历对二叉树进行序列化
public class TreeToString {
public String SerializeBinaryTree1(TreeNode root) {
//注意:Java中String是不可改变的,不能进行引用传递,改为使用StringBuffer
StringBuilder res=new StringBuilder("");
//调用递归方法完成二叉树遍历序列化
this.preOrder(root,res);
//返回结果
return res.toString();
}
//递归方法,用来先序遍历二叉树同时将其序列化为字符串
private void preOrder(TreeNode root, StringBuilder str){
//递归结束的边界条件
if(root==null){
str.append("#!");
return;
}
//添加节点值
str.append(root.val+"!");
//遍历左子树
this.preOrder(root.left,str);
//遍历右子树
this.preOrder(root.right,str);
}
}
2. 非递归写法
//使用非递归先序遍历对二叉树进行序列化
public class TreeToString {
public String SerializeBinaryTree2(TreeNode root) {
//注意:Java中String是不可改变的,不能进行引用传递,改为使用StringBuffer
StringBuilder res=new StringBuilder("");
//调用递归方法完成二叉树遍历序列化
this.preOrder2(root,res);
//返回结果
return res.toString();
}
private void preOrder2(TreeNode root,StringBuilder str){
Stack<TreeNode> stack=new Stack<>();
//创建指针cur表示当前正在访问的结点,初始值为root
TreeNode cur=root;
//将根结点放入栈中
stack.push(cur);
while(!stack.isEmpty()){
cur=stack.pop();
if(cur==null){
str.append("#!");
}else{
//只要cur!=null不管cur的left和right是否是null都要压入栈中
str.append(cur.val).append("!");
stack.push(cur.right);
stack.push(cur.left);
}
}
}
}
反序列化二叉树
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
先序序列化结果重构二叉树 String[] nodes=str.split("!");
/由每个结点的结束符号划分序列化结果序列,得到各个结点值;然后按照先序遍历的顺序“根左右”的特性,遍历nodes数组建立二叉树:
- 当前遍历元素
非#
则作为一个结点插入树中作为上一结点的左儿子; - 当前遍历元素为
#
则表示此子树已结束,遍历下一元素作为上一结点的右儿子;
public class Solution {
//已知由先序遍历得到的字符串str,将其恢复为一棵二叉树,并返回根结点
TreeNode Deserialize(String str) {
if(str==null||str.length()<=0) return null;
//将字符串按照"!"拆分为数组
String[] strs=str.split("!");
//调用递归方法deSerializeCore()方法来实现重建二叉树的功能,返回根结点
TreeNode root=this.deSerializeCore(strs);
return root;
}
//index用来遍历字符串
int index=0;
private TreeNode deSerializeCore(String[] strs){
if("#".equals(strs[index])){
//#表示空节点,不再建立子树返回null,返回前要将index++
index++;
return null;
}else{
//如果不为空结点,则先恢复这个结点
TreeNode newNode=new TreeNode(0);
newNode.val=Integer.parseInt(strs[index]);
index++;
//递归建立左子树
newNode.left=this.deSerializeCore(strs);
//递归建立右子树
newNode.right=this.deSerializeCore(strs);
//左右子树建立完成后返回根结点
return newNode;
}
}
}