[LeetCode] 297. Serialize and Deserialize Binary Tree 二叉树的序列化和反序列化

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.

Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.

Example: 

You may serialize the following tree:

    1
   / \
  2   3
     / \
    4   5

as "[1,2,3,null,null,4,5]"

Clarification: The above format is the same as how LeetCode serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.

Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.

序列化是是指将数据结构或物件状态转换成可取用格式(例如存成档案,存于缓冲,或经由网络中传送),以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程,还原的过程叫做反序列化。比如例子中的把树序列化成数组,还可以由这个数组在反序列化变回树。

根据题目序列化的形式,可以先序遍历的递归或者层序遍历的非递归:

需要接入输入和输出字符串流istringstream和ostringstream,对于序列化,从根节点开始,如果节点存在,则将值存入输出字符串流,然后分别对其左右子节点递归调用序列化函数即可。对于反序列化,先读入第一个字符生成一个根节点,然后再对根节点的左右子节点递归调用去序列化函数即可。

Java:level order traversal

// Encodes a tree to a single string.
public String serialize(TreeNode root) {
    if(root==null){
        return "";
    }
 
    StringBuilder sb = new StringBuilder();
 
    LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
 
    queue.add(root);
    while(!queue.isEmpty()){
        TreeNode t = queue.poll();
        if(t!=null){
            sb.append(String.valueOf(t.val) + ",");
            queue.add(t.left);
            queue.add(t.right);
        }else{
            sb.append("#,");
        }
    }
 
    sb.deleteCharAt(sb.length()-1);
    System.out.println(sb.toString());
    return sb.toString();
}
 
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
    if(data==null || data.length()==0)
        return null;
 
    String[] arr = data.split(",");
    TreeNode root = new TreeNode(Integer.parseInt(arr[0]));
 
 
    LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
    queue.add(root);
 
    int i=1;
    while(!queue.isEmpty()){
        TreeNode t = queue.poll();
 
        if(t==null)
            continue;
 
        if(!arr[i].equals("#")){
            t.left = new TreeNode(Integer.parseInt(arr[i]));    
            queue.offer(t.left);
 
        }else{
            t.left = null;
            queue.offer(null);
        }
        i++;
 
        if(!arr[i].equals("#")){
            t.right = new TreeNode(Integer.parseInt(arr[i]));    
            queue.offer(t.right);
 
        }else{
            t.right = null;
            queue.offer(null);
        }
        i++;
    }
 
    return root;
}

Java: Preorder traversal

// Encodes a tree to a single string.
public String serialize(TreeNode root) {
    if(root==null)
        return null;
 
    Stack<TreeNode> stack = new Stack<TreeNode>();
    stack.push(root);
    StringBuilder sb = new StringBuilder();
 
    while(!stack.isEmpty()){
        TreeNode h = stack.pop();   
        if(h!=null){
            sb.append(h.val+",");
            stack.push(h.right);
            stack.push(h.left);  
        }else{
            sb.append("#,");
        }
    }
 
    return sb.toString().substring(0, sb.length()-1);
}
 
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
    if(data == null)
        return null;
 
    int[] t = {0};
    String[] arr = data.split(",");
 
    return helper(arr, t);
}
 
public TreeNode helper(String[] arr, int[] t){
    if(arr[t[0]].equals("#")){
        return null;
    }
 
    TreeNode root = new TreeNode(Integer.parseInt(arr[t[0]]));
 
    t[0]=t[0]+1;
    root.left = helper(arr, t);
    t[0]=t[0]+1;
    root.right = helper(arr, t);
 
    return root;
}

Java:

public class Codec {
    private static final String spliter = ",";
    private static final String NN = "X";

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        buildString(root, sb);
        return sb.toString();
    }

    private void buildString(TreeNode node, StringBuilder sb) {
        if (node == null) {
            sb.append(NN).append(spliter);
        } else {
            sb.append(node.val).append(spliter);
            buildString(node.left, sb);
            buildString(node.right,sb);
        }
    }
    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        Deque<String> nodes = new LinkedList<>();
        nodes.addAll(Arrays.asList(data.split(spliter)));
        return buildTree(nodes);
    }
    
    private TreeNode buildTree(Deque<String> nodes) {
        String val = nodes.remove();
        if (val.equals(NN)) return null;
        else {
            TreeNode node = new TreeNode(Integer.valueOf(val));
            node.left = buildTree(nodes);
            node.right = buildTree(nodes);
            return node;
        }
    }
}  

Python:

class Codec:

    def serialize(self, root):
        def serializeHelper(node):
            if not node:
                vals.append('#')
            else:
                vals.append(str(node.val))
                serializeHelper(node.left)
                serializeHelper(node.right)
        vals = []
        serializeHelper(root)
        return ' '.join(vals)


    def deserialize(self, data):
        def deserializeHelper():
            val = next(vals)
            if val == '#':
                return None
            else:
                node = TreeNode(int(val))
                node.left = deserializeHelper()
                node.right = deserializeHelper()
                return node
        def isplit(source, sep):
            sepsize = len(sep)
            start = 0
            while True:
                idx = source.find(sep, start)
                if idx == -1:
                    yield source[start:]
                    return
                yield source[start:idx]
                start = idx + sepsize
        vals = iter(isplit(data, ' '))
        return deserializeHelper()

 Python:

class Codec:

    def serialize(self, root):
        def doit(node):
            if node:
                vals.append(str(node.val))
                doit(node.left)
                doit(node.right)
            else:
                vals.append('#')
        vals = []
        doit(root)
        return ' '.join(vals)

    def deserialize(self, data):
        def doit():
            val = next(vals)
            if val == '#':
                return None
            node = TreeNode(int(val))
            node.left = doit()
            node.right = doit()
            return node
        vals = iter(data.split())
        return doit()  

C++:

class Codec {
public:
    string serialize(TreeNode* root) {
        ostringstream out;
        serialize(root, out);
        return out.str();
    }
 
    TreeNode* deserialize(string data) {
        istringstream in(data);
        return deserialize(in);
    }
private:
    void serialize(TreeNode* root, ostringstream& out) {
        if (!root) {
            out << "# ";
            return;
        }        
        out << root->val << " ";
        serialize(root->left, out);
        serialize(root->right, out);
    }
    
    TreeNode* deserialize(istringstream& in) {
        string val;
        in >> val;
        if (val == "#") return nullptr;        
        TreeNode* root = new TreeNode(stoi(val));        
        root->left = deserialize(in);
        root->right = deserialize(in);        
        return root;
    }
};

C++:

class Codec {
public:
 
    string serialize(TreeNode* root) {
        ostringstream out;
        serialize(root, out);
        return out.str();
    }
 
    TreeNode* deserialize(string data) {
        istringstream in(data);
        return deserialize(in);
    }
private:
    enum STATUS {
        ROOT_NULL = 0x0,
        ROOT = 0x1,
        LEFT = 0x2,
        RIGHT = 0x4
    };
    
    void serialize(TreeNode* root, ostringstream& out) {
        char status = 0;
        if (root) status |= ROOT;
        if (root && root->left) status |= LEFT;
        if (root && root->right) status |= RIGHT;
        out.write(&status, sizeof(char));        
        if (!root) return;
        out.write(reinterpret_cast<char*>(&(root->val)), sizeof(root->val));
        if (root->left) serialize(root->left, out);
        if (root->right) serialize(root->right, out);
    }
    
    TreeNode* deserialize(istringstream& in) {
        char status;
        in.read(&status, sizeof(char));
        if (!status & ROOT) return nullptr;
        auto root = new TreeNode(0);
        in.read(reinterpret_cast<char*>(&root->val), sizeof(root->val));        
        root->left = (status & LEFT) ? deserialize(in) : nullptr;
        root->right = (status & RIGHT) ? deserialize(in) : nullptr;
        return root;
    }
};

 

Followup: 如果是 n-ary怎么办?

   

All LeetCode Questions List 题目汇总

  

 

 

 

posted @ 2018-03-05 14:04  轻风舞动  阅读(993)  评论(0编辑  收藏  举报