如何在Java中对二进制树进行序列化和反序列化

367 阅读4分钟

在Java中对二进制树进行序列化和反序列化是最受欢迎的代码挑战之一,可以测试你的熟练程度。

序列化是将数据结构或对象转换为一个比特序列或字符串的过程。

然后,代表该对象的字符串可以存储在文本文件中,或通过流传输给需要该数据的其他网络。

反序列化是将比特序列转换回其原始对象的过程,这样它就可以被编程语言在其代码中使用。

下图说明了二进制树的序列化和反序列化过程:

Serialize and Deserialize graph in Java

Java中的序列化和反序列化图

(serialize-deserialize-binary-tree-java.png)

上图中的标记# ,用来表示null 值。它意味着该节点没有更多的子节点。

本教程将帮助你学习如何在Java中对二叉树进行序列化和反序列化。

但首先,让我们创建一个TreeNode ,这个类将用于创建二叉树。

在Java中创建二叉树类

下面的TreeNode 类是用来在Java中创建一个二叉树的:

public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}

然后你可以在main() 方法中创建二叉树,如下图所示:

TreeNode root = new TreeNode(9);
root.left = new TreeNode(3);
root.right = new TreeNode(5);
root.right.right = new TreeNode(6);
root.left.left = new TreeNode(1);
root.left.right = new TreeNode(7);

现在你可以创建一棵二叉树了,让我们来学习如何将二叉树对象序列化。

在Java中序列化一个二叉树

首先,为一个名为BinaryTreeCodec 或简称BTCodec 的Java类创建一个新文件。

在这个类中,创建一个名为serialize() 的新方法,返回一个String ,并接受一个TreeNode 对象:

class BTCodec {
String serialize(TreeNode root) {
}
}

为了序列化TreeNode 对象,你需要递归地调用serialize() 方法,将root.val 的值返回为字符串,并将它们串联起来。

rootnull ,你需要返回# 符号作为null 的标记:

String serialize(TreeNode root) {
if (root == null) {
return "#";
}
return "" + root.val + "," + serialize(root.left) + "," + serialize(root.right);
}

你可以在你的Java项目的main() 方法中试用serialize() 方法:

public class Main {
public static void main(String[] args) {
TreeNode root = new TreeNode(9);
root.left = new TreeNode(3);
root.right = new TreeNode(5);
root.right.right = new TreeNode(6);
root.left.left = new TreeNode(1);
root.left.right = new TreeNode(7);
 BTCodec codec = new BTCodec();
 String data = codec.serialize(root);
 System.out.println(data);
 }
}

上面的data 字符串的输出应该是这样的:

9,3,1,#,#,7,#,#,5,#,6,#,#

上面的序列化过程将从根部开始遍历二进制树的深度。

一旦到达最左边的节点的末端,该方法将开始遍历右边的子节点。这也被称为前序遍历方法。

现在你可以将Java中的二叉树序列化为String ,现在是时候学习如何将它反序列化为二叉树了。

在Java中对二叉树进行反序列化

与序列化过程类似,你可以在ArrayList 对象的帮助下将一个String 反序列化为二叉树。

回到BinaryTreeCodec 类中,你需要定义一个名为deserialize() 的新方法,该方法返回一个TreeNode ,并接受一个String 作为其参数:

TreeNode deserialize(String data) {}

首先,你需要检查data 字符串是否是null 。如果是,你可以返回一个null 的值。

data 字符串不是null ,那么你可以继续将该字符串再次分割成一个ArrayList

之后,调用一个名为deserial() 的辅助函数,如下所示。接下来你将定义这个方法:

TreeNode deserialize(String data) {
if (data == null){
return null;
}
List<String> values = new ArrayList<>(Arrays.asList(data.split(",")));
return deserial(values);
}

上面的deserial() 方法将是一个你可以递归调用的方法,从给定的ArrayList 建立二叉树。

下面是deserial() 方法的代码:

private TreeNode deserial(List<String> values){
String val = values.remove(0);
if (val.equals("#")) return null;
TreeNode root = new TreeNode(Integer.parseInt(val));
root.left = deserial(values);
root.right = deserial(values);
return root;
}

首先,你使用remove() 方法来获取存储在ArrayList 中的第一个元素。

当值等于# ,你可以返回null ,因为这意味着树节点没有任何更多的值。

如果值不是null ,那么你就创建一个新的TreeNode 对象,并使用Integer.parseInt() 方法将String 值转换成int

然后,你递归地调用deserial() 方法,直到values 列表中的所有元素都被处理。

该方法将返回你所创建的TreeNoderoot 节点。

测试代码

现在,BinaryTreeCodec 类已经完成,你可以测试代码,如下所示:

public class Main {
public static void main(String[] args) {
TreeNode root = new TreeNode(9);
root.left = new TreeNode(3);
root.right = new TreeNode(5);
root.right.right = new TreeNode(6);
root.left.left = new TreeNode(1);
root.left.right = new TreeNode(7);
BTCodec codec = new BTCodec();
String data = codec.serialize(root);
System.out.println(data);
TreeNode deserialized = codec.deserialize(data);
System.out.println(deserialized.val);
System.out.println(deserialized.left.val);
System.out.println(deserialized.right.val);
System.out.println(deserialized.right.right.val);
System.out.println(deserialized.left.left.val);
System.out.println(deserialized.left.right.val);
}
}

上述代码的输出将如下:

9,3,1,#,#,7,#,#,5,#,6,#,#
9
3
5
6
1
7

TreeNode 已经使用BinaryTreeCodec 类成功地进行了序列化和反序列化。

你可以在以下GitHub资源库中获得本教程的所有代码。

使用Java对二进制树进行序列化和反序列化

在本教程中,你已经学会了如何对二叉树进行序列化和反序列化,干得好!😉