题目依旧来自《剑指Offer》和牛客网在线编程。
【题目】实现两个函数,分别实现序列化与反序列化二叉树。
/* public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } */ public class Solution { String Serialize(TreeNode root) { } TreeNode Deserialize(String str) { } }
【分析1】首先明确序列化与反序列化二叉树。所谓的序列化二叉树就是按照树的某种遍历方式遍历二叉树,将每个结点的值以某种特殊符号(例如,)分隔保存到一个字符串中,如果结点为空,则使用另外一种特殊符号(例如#)表示。反序列化的意思就是根据序列化的字符串重构出该二叉树。这里需要特别说明一点的是,遍历到叶子结点后,还需要继续向下遍历,结点为空,则用特殊字符(例如#)表示。
【分析2】对于二叉树的遍历方式选择上,原则上前、中、后和层次遍历都是可以的。但是为了能够很容易的获取二叉树的根结点,因此我们可以选择前序遍历顺序,这样遍历出来的第一个元素就是二叉树的根结点对应的值。
【分析3】对于二叉树的序列化来说,现在就变成了一个前序遍历二叉树的过程。如果当前结点不为空,则将当前结点对应的值加入到字符串中;如果当前结点为空,则将特殊字符(例如,#)加入到字符串中。
【分析4】根据前序序列化的二叉树字符串,我们需要重构该二叉树。根据前序遍历的特点,我们在获取根结点后,首先应该一直向左构建左子树,直到遇到空结点。如果当前结点为空,则应该返回到它的父结点,然后构造它的父结点的右子树。以此类推,显然这也是一个递归进行的过程。
【代码】
/* public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } */ public class Solution { public int index = -1; String Serialize(TreeNode root) { StringBuilder builder = new StringBuilder(); pre(root,builder); return builder.toString(); } TreeNode Deserialize(String str) { /*String[] array = str.split("!"); TreeNode root = null; if("#".equals(array[0])) return root; else{ root.val = Integer.valueOf(array[0]); TreeNode p = root; TreeNode q = root; int flag = 1 for(int i = 1;i < array.length;++i){ if("#".equals(array[i] && "#".equals(array[i+1]){ q = p; }else { TreeNode temp; temp.val = Integer.valueOf(array[i]); q.left = temp; p = q; q = temp; } } } return root;*/ index++; String[] DLRseq = str.split(","); TreeNode leave = null; if(!DLRseq[index].equals("#")){ leave = new TreeNode(Integer.valueOf(DLRseq[index])); leave.left = Deserialize(str); leave.right = Deserialize(str); } return leave; } void pre(TreeNode root,StringBuilder builder){ if(root == null){ builder.append("#,"); }else{ builder.append(root.val+","); pre(root.left,builder); pre(root.right,builder); } } }