二叉树序列化/反序列化

柔光的暖阳◎ 2022-04-22 14:36 332阅读 0赞

二叉树被记录成文件的过程,为二叉树的序列化

通过文件重新建立原来的二叉树的过程,为二叉树的反序列化

设计方案并实现。

(已知结点类型为32位整型)

思路:先序遍历实现。

因为要写入文件,我们要把二叉树序列化为一个字符串。

首先,我们要规定,一个结点结束后的标志:“!”

然后就可以通过先序遍历生成先序序列了。

但是,众所周知,只靠先序序列是无法确定一个唯一的二叉树的,原因分析如下:

比如序列1!2!3!

我们知道1是根,但是对于2,可以作为左孩子,也可以作为右孩子:

201811261735360.png2018112617355292.png

对于3,我们仍然无法确定,应该作为左孩子还是右孩子,情况显得更加复杂:

20181126173727821.png20181126173745503.png

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hlYnR1NjY2_size_16_color_FFFFFF_t_702018112617384090.png

20181126173947552.png

原因:我们对于当前结点,插入新结点是无法判断插入位置,是应该作为左孩子,还是作为右孩子。

因为我们的NULL并未表示出来。

如果我们把NULL也用一个符号表示出来:

比如

20181126173947552.png

1!2!#!#!3!#!#!

我们再按照先序遍历的顺序重建:

对于1,插入2时,就确定要作为左孩子,因为左孩子不为空。

然后接下来两个#,我们就知道了2的左右孩子为空,然后重建1的右子树即可。

我们定义结点:

  1. public static class Node {
  2. public int value;
  3. public Node left;
  4. public Node right;
  5. public Node(int data) {
  6. this.value = data;
  7. }
  8. }

序列化:

  1. public static String serialByPre(Node head) {
  2. if (head == null) {
  3. return "#!";
  4. }
  5. String res = head.value + "!";
  6. res += serialByPre(head.left);
  7. res += serialByPre(head.right);
  8. return res;
  9. }
  10. public static Node reconByPreString(String preStr) {
  11. //先把字符串转化为结点序列
  12. String[] values = preStr.split("!");
  13. Queue<String> queue = new LinkedList<String>();
  14. for (int i = 0; i != values.length; i++) {
  15. queue.offer(values[i]);
  16. }
  17. return reconPreOrder(queue);
  18. }
  19. public static Node reconPreOrder(Queue<String> queue) {
  20. String value = queue.poll();
  21. if (value.equals("#")) {
  22. return null;//遇空
  23. }
  24. Node head = new Node(Integer.valueOf(value));
  25. head.left = reconPreOrder(queue);
  26. head.right = reconPreOrder(queue);
  27. return head;
  28. }

这样并未改变先序遍历的时空复杂度,解决了先序序列确定唯一一颗树的问题,实现了二叉树序列化和反序列化。

发表评论

表情:
评论列表 (有 0 条评论,332人围观)

还没有评论,来说两句吧...

相关阅读

    相关 序列/序列

    二叉树被记录成文件的过程,为二叉树的序列化 通过文件重新建立原来的二叉树的过程,为二叉树的反序列化 设计方案并实现。 (已知结点类型为32位整型) 思路:先序遍历实现。