刷题——对二进制树进行序列化和反序列化

原题:

其实我不怎么会这种类型的题目,所以这里的代码主要参考了九章上面的答案。

下面是我的代码:

/**
 * 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;
        }
        // 用vector来存储节点内容,记住这里左边优先,后面复原的时候会用到
        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);
        }
        // 因为节点末端检测的时候会检测到大量的NULL并被添加进holder中,所以需要移除掉
        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();
            }
            // 当执行到右节点时则将当前处理的节点弹出,进入下一个节点(顶->左->右)
            isLeftChild = !isLeftChild;
        }
        return root;
    }
};

注释里面思路已经说得挺清楚的了,这里只是补充几句。总体上来看其实序列化要简单一点,直接遍历一遍树的内容并按照一定规律转化成字符串就可以了。其实这里用到vectoer是为了方便操作,大概的操作流程是:

序列化:

右边就是vector的情况(11之类的只是编号),左边的就是树的结构和内容。序列化的主要思路就是先将遍历一遍binary tree的内容,然后按照一定规律(记住,这里的规律是先左后右,后面反序列化的时候会用到这个规律)保存在vector中。

反序列化的流程差不多,只是加了个对上一层节点的弹出。

这里补充下相关的用法:C++ queue(STL queue)用法详解

虽然是queue的,但是实际上vector的也差不多,最重要的部分其实是这张图:

大概就是这样。

posted @ 2019-07-09 01:35  夜溅樱  阅读(225)  评论(0编辑  收藏  举报