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.


分析:

递归:

利用先序遍历,空节点用特殊符号如"#"代替,为了在反序列时找到每个节点,序列间节点间可以用' , '隔开。

class Codec {
public:
    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        if (root == nullptr) return "#";
        return to_string(root->val)+","+serialize(root->left)+","+serialize(root->right);
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        return mydeserialize(data);
    }
    TreeNode* mydeserialize(string& data) {
        if (data[0]=='#') {
            if(data.size() > 1) data = data.substr(2);
            return nullptr;
        } else {
            TreeNode* node = new TreeNode(helper(data));
            node->left = mydeserialize(data);
            node->right = mydeserialize(data);
            return node;
        }
    }
private:
    int helper(string& data) {
        int pos = data.find(',');
        int val = stoi(data.substr(0,pos));
        data = data.substr(pos+1);
        return val;
    }
};

在剑指offer中,函数的返回类型为char*,因此需要与字符串进行转换:

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:    
    char* Serialize(TreeNode *root) {    
        string s = serializeHelper(root);
        char *str = new char[s.length() + 1];
        strcpy(str, s.c_str());
        return str;
    }
    
    string serializeHelper(TreeNode *node) {
        if (node == NULL) return "#";
        return to_string(node->val) + "," + serializeHelper(node->left) + "," + serializeHelper(node->right);
    }
    
    TreeNode* Deserialize(char *str) {
        string s(str);
        return myDeserialize(s);
    }
    
    TreeNode* myDeserialize(string &s) {
        if (s[0] == '#') {
            if (s.size() > 1) s= s.substr(2);
            return nullptr;
        } else {
            TreeNode *node = new TreeNode(helper(s));
            node->left = myDeserialize(s);
            node->right = myDeserialize(s);
            return node;
        }
    }
private:
    int helper(string &s) {
        int pos = s.find(',');
        int val = stoi(s.substr(0, pos));
        s = s.substr(pos + 1);
        return val;
    }
};

但是,手动进行string与char*之间的转换效率很低:

*Runtime:*152ms,*Memory:*534.6MB

因此采用stringstream可以使代码更加简洁并且效率更高:

*Runtime:*36ms,Memory: 34.3MB

class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        if (root == NULL) return "#";
        return to_string(root->val) + "," + serialize(root->left) + "," + serialize(root->right);
    }

    TreeNode* deserialize(string data) {
        if (data == "#") return NULL;
        stringstream s(data);
        return makeDeserialize(s);
    }
    
    TreeNode* makeDeserialize(stringstream& s) {
        string str;
        getline(s, str, ',');
        if (str == "#") {
            return NULL;
        } else {
            TreeNode* root = new TreeNode(stoi(str));
            root->left = makeDeserialize(s);
            root->right = makeDeserialize(s);
            return root;
        }
    }
};

参考来源: