Brush title - serialize and deserialize binary tree

Keywords: PHP

Original title:

In fact, I don't know this type of question very well, so the code here mainly refers to the answers above the nine chapters.

Here is my code:

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */


class Solution {
public:
    vector<string> split(const string &str, string str2del){
        vector<string> res_str;
        int lastindex = 0;
        int index = 0;
        
        while((index = str.find(str2del, lastindex))!=string::npos){
            res_str.push_back(str.substr(lastindex, index-lastindex));
            lastindex = index + str2del.length();
        }
        if(lastindex!=str.length()){
            res_str.push_back(str.substr(lastindex, str.length() - lastindex));
        }
        return res_str;
    }
    /**
     * This method will be invoked first, you should design your own algorithm 
     * to serialize a binary tree which denote by a root node to a string which
     * can be easily deserialized by your own "deserialize" method later.
     */
    string serialize(TreeNode * root) {
        if(root == NULL){
            return "{}";
        }
        vector<TreeNode *> holder;
        holder.push_back(root);
        // cout << holder.size() << endl;
        if(root == NULL){
            return NULL;
        }
        // Use vector to store node content. Remember that the left side is the priority. It will be used in later recovery.
        for(int i = 0; i < holder.size(); i++){
            TreeNode * node = holder[i];
            if (node == NULL){
                continue;
            }
            holder.push_back(node->left);
            holder.push_back(node->right);
        }
        // Because a large number of nulls will be detected and added to the holder during node end detection, it needs to be removed.
        while(holder[holder.size() - 1]==NULL){
            holder.pop_back();
        }
        string res_str = "{";
        res_str += to_string(holder[0]->val);
        for(int i = 1; i < holder.size(); i++){
            if(holder[i] == NULL){
                res_str+=",#";
            }
            else{
                res_str+=",";
                res_str+=to_string(holder[i]->val);
            }
        }
        res_str+="}";
        return res_str;
    }

    /**
     * This method will be invoked second, the argument data is what exactly
     * you serialized at method "serialize", that means the data is not given by
     * system, it's given by your own serialize method. So the format of data is
     * designed by yourself, and deserialize it here as you serialize it in 
     * "serialize" method.
     */
    TreeNode * deserialize(string &data) {
        if(data=="{}") return NULL;
        vector<string> val = split(data.substr(1, data.size() - 2), ",");
        queue<TreeNode *> Q;
        TreeNode *root = new TreeNode(atoi(val[0].c_str()));
        Q.push(root);
        bool isLeftChild=true;
        for(int i=1; i<val.size(); i++){
            if(val[i]!="#"){
                TreeNode *node = new TreeNode(atoi(val[i].c_str()));
                if(isLeftChild) Q.front()->left = node;
                else Q.front()->right = node;
                Q.push(node);
            }
            if(!isLeftChild){
                Q.pop();
            }
            // When executing to the right node, the currently processed node will pop up and enter the next node (top - > left - > right)
            isLeftChild = !isLeftChild;
        }
        return root;
    }
};

The way of thinking in the notes is quite clear. Here is just a few additional words. Generally speaking, serialization is a little easier. You can directly traverse the contents of the tree and convert them into strings according to certain rules. In fact, vectocoer is used to facilitate operation. The approximate operation process is as follows:

Serialization:

On the right is the case of vector (11 and so on is just the number), on the left is the structure and content of the tree. The main idea of serialization is to traverse the content of binary tree once, and then save it in vector according to a certain rule (remember, the rule here is first left then right, which will be used when deserializing later).

The process of deserialization is almost the same, just adding a pop-up to the previous level node.

Here are the relevant uses: A detailed explanation of the usage of C++ queue(STL queue)

Although it's queue, actually it's vector. The most important part is this picture:

That's about it.

Posted by delorian on Sat, 02 Nov 2019 09:24:24 -0700