leetcode-297. 二叉树的序列化与反序列化

      思路:通过前序、后续、或者层次遍历二叉树,用一个字符串保存节点的值,要注意的是,每个节点的值之后要添加一个特殊符号(比如下划线)分隔,否则可能无法区分节点的值。

      比如一个节点的值可能是12,不加下划线的话,反序列化时就分不清楚,12表示的是一个值为12的节点,或者两个节点,其值分别为1,2。

split函数用来去除原来作为分割的符号,本文中用来去除下划线。

总之:怎么序列化二叉树就怎么反序列化二叉树

还要注意节点值为负号的情况,为了正确识别序列化后字符串中的负号,split中用来保存结果的容器可以选用vector.

下面给出两种方法:

方法一:按层次遍历的顺序序列化和反序列化

class Codec {//按层序列化
private:
    void split(const string &src,vector& vec,const char& delimiter){
        vec.clear();
        istringstream iss(src);
        string tmp;
        while(getline(iss,tmp,delimiter)){
            if(tmp!="#")
                vec.push_back(stoi(tmp));//注意转换成int
            else
                vec.push_back(0x3f3f3f3f);//tmp为“#”时,推入一个特殊的数
        }
    }
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        if(root==NULL)
            return "";
        string str;
        queueq;
        q.push(root);
        str+=to_string(root->val)+'_';//不要忘了记录头结点的值
        while(!q.empty()){
            TreeNode* cur=q.front();
            q.pop();
            if(cur->left) {
                q.push(cur->left);
                str+=to_string(cur->left->val)+"_";
            }else{//没有左孩子时
                str+="#_";
            }
            
            if(cur->right) {
              q.push(cur->right);
             str+=to_string(cur->right->val)+"_";
            }else{
                 str+="#_";
            }
        }
        return str;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        if(data.empty())
            return NULL;
       vector vec;//用来保存
        split(data,vec,'_');//以下划线做分割符
        size_t pos=0;
        TreeNode* newRoot=new TreeNode(vec[pos++]);//生成一个新的头结点 
        
        queue q;
        q.push(newRoot);
        TreeNode* cur=NULL;
        while(!q.empty()){
           cur=q.front();
           q.pop();
           cur->left=(vec[pos]==0x3f3f3f3f)?NULL:new TreeNode(vec[pos]);
            ++pos;
           cur->right=(vec[pos]==0x3f3f3f3f)?NULL:new TreeNode(vec[pos]);
            ++pos;
           if(cur->left)
               q.push(cur->left);
           if(cur->right)
               q.push(cur->right);
        }
        return newRoot;
      
    }
};

方法二:按照前序遍历的方法序列化和反序列化

class Codec {//按照前序遍历来序列化
private:
    void _serialize(TreeNode* cur,string &s){
        if(cur==NULL){
            s+="#_";
            return ;
        }
        s+=to_string(cur->val)+"_";
        _serialize(cur->left,s);
         _serialize(cur->right,s);
         return;
    }
   void split(const string& src,vector& vec,const char delimiter){//不要用string去接收结果
       vec.clear();//若用string,则处理负号比较麻烦
       istringstream iss(src);
       string tmp;
       while(getline(iss,tmp,delimiter)){
           if(tmp=="#")
           vec.push_back(0x3f3f3f3f);//注意这里的特殊处理
           else
        vec.push_back(stoi(tmp));
       }
   }
TreeNode* _deserialize(const vector& data,int &idx){
     if(data.empty()||idx>=data.size()||data[idx]==0x3f3f3f3f)
         return NULL;
     TreeNode* cur=new TreeNode(data[idx]);
     cur->left=_deserialize(data,++idx);
     cur->right=_deserialize(data,++idx);
     return cur;
}
    
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        if(root==NULL)
           return "";
        string s;
         _serialize(root,s);
        return s;
        
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        if(data.empty())
            return NULL;
        vector res;
        split(data,res,'_');
        int pos=0;
        TreeNode *newHead=_deserialize(res,pos);
        return newHead;
    }
};

 

你可能感兴趣的:(刷题记录,C++,算法与数据结构)