剑指Offer对答如流系列 面试题37:序列化二叉树

题目描述

请实现两个函数,分别用来序列化和反序列化二叉树。

树的结构定义如下:

    public class Node {
        int val = 0;
        Node left = null;
        Node right = null;

        public Node(int val) {
            this.val = val;
        }
    }

问题分析

一般情况下,需要采用前/后序遍历和中序遍历才能确定一个二叉树,具体的内容我们之前探讨过 剑指Offer对答如流系列 - 重建二叉树

但是采用这种方式进行序列化和反序列化代价还是比较大的,于是我们要考虑另外的情况了。

如果采用前序遍历(遍历特点 根节点 --> 左子树 --> 右子树),将空结点(null)输出为一个特殊符号(如“$”),特殊符号充当边界,这个时候就可以确定一个二叉树了。

序列化:前序遍历的过程中,将遇见的空结点序列化为“$”,每个结点间使用逗号分隔开。

反序列化:同样使用前序遍历,遇见一个新数字(或者$)就建立一个新结点。

问题解决

 String Serialize(Node node) {
        StringBuilder sb = new StringBuilder();
        if (node == null) {
            sb.append("$,");
        } else {
            sb.append(node.val + ",");
            sb.append(Serialize(node.left));
            sb.append(Serialize(node.right));
        }
        return sb.toString();
    }

    // 全局Int变量index(在字符串上的移动的索引),以获得字符串中当前的节点值
    private int index = 0;
    Node Deserialize(String str) {
        
        Node node = null;
        if (str == null || str.length() == 0) {
            return node;
        }
        int start = index;
        while (str.charAt(index) != ',') {
            index++;
        }
        if (!str.substring(start, index).equals("$")) {
            node = new Node(Integer.parseInt(str.substring(start, index)));
            index++;
            node.left = Deserialize(str);
            node.right = Deserialize(str);
        } else {
            index++;
        }
        return node;
    }