二叉树的序列化&反序列化
一. 题目:
二叉树被记录成文件的过程叫作二叉树的序列化,通过文件内容重建原来二叉树的过程叫作二叉树的反序列化。
给定一棵二叉树的头节点head,并已知二叉树节点值的类型为32位整型。
二. 解题思路:
通过先序遍历实现序列化和反序列化:
先介绍先序遍历下的序列化过程,首先假设序列化的结果字符串为str,初始时str=""。
先序遍历二叉树,如果遇到null节点,就在str的末尾加上"#!","#"表示这个节点为空, 节点值不存在,”!”表示一个值的结束;
如果遇到不为空的节点,假设节点值为3,就在str的末尾加上"3!"。
比如图一所示的二叉树:
根据上图所示,可以得到先序遍历序列化,最后的结果字符串str为:12!3!#!#!#!。
为什么在每一个节点值的后面都要加上"!"呢?因为如果不标记一个值的结束,最后产生的结果会有歧义,如图二所示:
如果不在一个值结束时加入特殊字符,那么图一和图二的先序遍历序列化结果都是123###。也就是说,生成的字符串并不代表唯一的树。
三. 代码实现:
1. 序列化&反序列化:
public static class Node {public int value;public Node left;public Node right;public Node(int data) {this.value = data;}}// 序列化public static String SerializeByPre(Node head) {// 判断树是否为空if (head == null) {return "#!";}String res = head.value + "!";res += SerializeByPre(head.left);res += SerializeByPre(head.right);return res;}// 解析字符串public static Node reconByPre(String preStr) {// 解析字符串String[] split = preStr.split("!");Queue<String> queue = new LinkedList<>();// 把解析后的字符串放入到队列中for (int i = 0; i != split.length; i++) {queue.offer(split[i]);}return reconPreOrder(queue);}// 反序列化private static Node reconPreOrder(Queue<String> queue) {// 开始反序列化String value = queue.poll();// 判空if (value.equals("#")) {return null;}// 构建二叉树Node head = new Node(Integer.valueOf(value));head.left = reconPreOrder(queue);head.right = reconPreOrder(queue);return head;}
2. 打印输出序列化&反序列化:
// 这里打印二叉树使用的方法,就是上一篇文章:直观打印二叉树public static void printTree(Node head) {System.out.println("Binary Tree:" + "\n");printInOrder(head, 0, "H", 10);System.out.println();}public static void printInOrder(Node head, int height, String to, int len) {if (head == null) {return;}printInOrder(head.right, height + 1, "v", len);String val = to + head.value + to;int lenM = val.length();int lenL = (len - lenM) / 2;int lenR = len - lenM - lenL;val = getSpace(lenL) + val + getSpace(lenR);System.out.println(getSpace(height * len) + val);printInOrder(head.left, height + 1, "^", len);}public static String getSpace(int num) {String space = " ";StringBuffer buf = new StringBuffer("");for (int i = 0; i < num; i++) {buf.append(space);}return buf.toString();}public static void main(String[] args) {Node head = new Node(1);head.left = new Node(2);head.right = new Node(3);head.left.left = new Node(4);String res = SerializeByPre(head);System.out.println("序列化结果: " + res);System.out.println("\n" + "反序列化结果: ");Node head1 = reconByPre(res);printTree(head1);}
3. 运行效果图:
如果不懂怎么打印二叉树的小伙伴请看这篇:
总结:二叉树的序列化&反序列化听起来挺高大上的,搞通原理后,也就是那样了,还是很清晰明了的,实现起来也很简单。
