297. 二叉树的序列化与反序列化
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
提示: 输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
示例 4:
输入:root = [1,2]
输出:[1,2]
运行结果
方法一:前序遍历
方法二:后序遍历
方法三:层序遍历
解题思路
方法一:前序遍历
利用前序遍历将二叉树序列化为字符串进行保存
求出各节点的值
反序列化:前序的第一个节点为根节点,之后是左子树和右子树。依次递归反序列化
方法二:后序遍历
利用后序遍历将二叉树序列化为字符串进行保存
求出各节点的值
反序列化:前序的最后一个节点为根节点,之后倒叙是右子树和左子树。依次递归反序列化
方法三:层序遍历
利用层序遍历框架求出其遍历节点,不过即使是空节点也要存入(直接入队列,出队列时再判断是否为空)
求出各节点的值
反序列化:第一个节点就是根节点,根节点入栈。之后就一直是左节点和右节点(并将其和出队的父节点连起来)。---递归操作:非空节点入栈,便于后续与孩子节点相连
除去具体操作,利用的也是层序遍历的框架
java代码
方法一:前序遍历
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ /*前序遍历 public class Codec { // Encodes a tree to a single string. public String serialize(TreeNode root) { StringBuilder sb=new StringBuilder(); serializehelp(root,sb); return sb.toString(); } //借助于前序遍历 public void serializehelp(TreeNode root,StringBuilder sb){ if(root == null){ sb.append("#").append(","); return; } sb.append(root.val).append(","); serializehelp(root.left,sb); serializehelp(root.right,sb); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { LinkedList<String> nodes=new LinkedList<>(); String[] tmp=data.split(","); for(String node:tmp){ nodes.addLast(node); } return deserializehelp(nodes); } public TreeNode deserializehelp(LinkedList<String> nodes){ if(nodes.isEmpty()) return null; String first=nodes.removeFirst(); if(first.equals("#")) return null; TreeNode root=new TreeNode(Integer.parseInt(first)); root.left=deserializehelp(nodes); root.right=deserializehelp(nodes); return root; } }*/ /*/后序遍历 public class Codec { // Encodes a tree to a single string. public String serialize(TreeNode root) { StringBuilder sb=new StringBuilder(); serializehelp(root,sb); return sb.toString(); } //借助于后序遍历 public void serializehelp(TreeNode root,StringBuilder sb){ if(root == null){ sb.append("#").append(","); return; } serializehelp(root.left,sb); serializehelp(root.right,sb); sb.append(root.val).append(","); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { LinkedList<String> nodes=new LinkedList<>(); String[] tmp=data.split(","); for(String node:tmp){ nodes.addLast(node); } return deserializehelp(nodes); } public TreeNode deserializehelp(LinkedList<String> nodes){ if(nodes.isEmpty()) return null; String first=nodes.removeLast(); if(first.equals("#")) return null; TreeNode root=new TreeNode(Integer.parseInt(first)); root.right=deserializehelp(nodes); root.left=deserializehelp(nodes); return root; } }*/ //层序遍历 public class Codec { // Encodes a tree to a single string. //借助于层序遍历 public String serialize(TreeNode root) { StringBuilder sb=new StringBuilder(); Queue<TreeNode> queue=new LinkedList<>(); if(root == null) return ""; queue.offer(root); while(!queue.isEmpty()){ TreeNode node=queue.poll(); if(node==null){ sb.append("#").append(","); continue; } sb.append(node.val).append(","); queue.offer(node.left); queue.offer(node.right); } return sb.toString(); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { if(data.isEmpty()) return null; String[] nodes=data.split(","); TreeNode root=new TreeNode(Integer.parseInt(nodes[0])); Queue<TreeNode> queue=new LinkedList<>(); queue.offer(root); for(int i=1;i<nodes.length;){ TreeNode parent=queue.poll(); String left = nodes[i++]; if(left.equals("#")){ parent.left=null; } else{ parent.left=new TreeNode(Integer.parseInt(left)); queue.offer(parent.left); } String right = nodes[i++]; if(right.equals("#")){ parent.right=null; } else{ parent.right=new TreeNode(Integer.parseInt(right)); queue.offer(parent.right); } } return root; } } // Your Codec object will be instantiated and called as such: // Codec ser = new Codec(); // Codec deser = new Codec(); // TreeNode ans = deser.deserialize(ser.serialize(root));