序列化二叉树:最直观的想法是,使用层序遍历的方式进行存储,对于某个叶子节点的空节点进行存储,同时保证不递归存储空节点对应的子节点。序列化指的是将二叉树转换为字符串;反序列化指的是将字符串转换为二叉树。序列化可以使用层序遍历,如何保证不递归存储空节点的子节点呢?那就是队列中不存储空节点,遇到空节点时只对字符串进行相应的处理,正因如此,应该是入队时处理字符串而不是出队时处理字符串;同时由于数值可能位数不止一位,故需要使用间隔符来分割数值。反序列化可以先根据间隔符分割数值,然后将根节点压入队列,使用变量k标记数组元素下标,初始赋值为根节点的左孩子元素下标,即k=1,当数组不越界时,先从队列中弹出元素,如果当前元素左孩子不为空,则构造左孩子节点,并将左孩子压入队列,同时设置当前元素与其左孩子之间的指针关系,右孩子同理,最后还要对数组元素下标k右移两位,最后返回root即可。即使用队列表示当前元素,保证其非空,使用数组表示当前元素的左右孩子,然后设置当前元素和左右孩子的指针关系。

// 序列化:将二叉树转换为字符串
char* Serialize(TreeNode *root) 
{    
   string str;
   queue<TreeNode *> que;
   if(!root) //空
     return nullptr;
   //根节点入队
   que.push(root);
   //入队的同时处理字符串 以感叹号分割数值 因为一个数值可能有多位
   str+=to_string(root->val)+'!';
   while(!que.empty())
   {
      TreeNode* ch=que.front();
      que.pop();
      if(ch->left)
      {
          que.push(ch->left);
          //由于不为空时会处理空字符串 所以不在出队的时候处理 而是在入队的时候处理
          str+=to_string(ch->left->val)+'!';
      }
      else
          str+='#';
      if(ch->right)
      {
          que.push(ch->right);
          str+=to_string(ch->right->val)+'!';
      }
      else
          str+='#';
      }
      //最后一位‘\0’ 不占长度但占空间
      char *p=new char[str.size()+1];
      strcpy(p,str.c_str());
      return p;
}
// 反序列化:将字符串转换为二叉树
TreeNode* Deserialize(char *str) 
{
    if(!str||str[0]=='#') //空
       return nullptr;
    string res=str;
    vector<string> vec; //分割数值
    //一个string一个数值 #表示空
    for(int i=0;i<res.size();i++)
    {
       if(res[i]=='#') //空
         vec.push_back("#");
       else
       {
         int j=i;
         while(res[j]!='!') //!分割数值
            j++;
         vec.push_back(res.substr(i,j-i));
         i=j; //i=j 因为出来后i会继续加一的
       }
    }
    //stoi将string转换为int 构造根节点
    TreeNode *root=new TreeNode(stoi(vec[0]));
    queue<TreeNode *> que;
    que.push(root);
    //根节点第一个孩子
    int k=1;
    //一共k个元素
    while(k<vec.size())
    {
       TreeNode *p=que.front();
       que.pop();
       //左孩子
       TreeNode* l=nullptr;
       //右孩子
       TreeNode* r=nullptr;
       if(vec[k]!="#") //左孩子非空
       {
          l=new TreeNode(stoi(vec[k]));
          que.push(l);
       }
       //默认是nullptr
       p->left=l;
       if(vec[k+1]!="#") //右孩子非空
       {
           r=new TreeNode(stoi(vec[k+1]));
           que.push(r);
       }
       //默认是nullptr
       p->right=r;
       k+=2; //指针后移两步 
    }
    return root;
}