leetcode 链接:297. 二叉树的序列化与反序列化

题目

序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。

请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。

提示: 输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。

示例:
[困难] 297. 二叉树的序列化与反序列化 - 图1

  1. 输入:root = [1,2,3,null,null,4,5]
  2. 输出:[1,2,3,null,null,4,5]
输入:root = []
输出:[]
输入:root = [1]
输出:[1]
输入:root = [1,2]
输出:[1,2]

解答 & 代码

解法一:先序遍历

  • 编码:递归先序遍历,最终将示例图片的二叉树编码为字符串 “1 2 n n 3 4 n n 5 n n”
  • 解码:先用 <sstream> 库的 istringstream 读字符串 data,方便之后按空格拆分。递归先序遍历。 ```cpp /**

    • Definition for a binary tree node.
    • struct TreeNode {
    • int val;
    • TreeNode *left;
    • TreeNode *right;
    • TreeNode(int x) : val(x), left(NULL), right(NULL) {}
    • }; / class Codec { private: // 递归编码(先序遍历) void dfsSerialize(TreeNode root, string& result) {

      if(root == NULL)    // 递归结束条件:空节点
      {
          result += "N ";
          return;
      }
      
      // 先序位置
      result += to_string(root->val) + " ";
      // 递归处理左右子树
      dfsSerialize(root->left, result);
      dfsSerialize(root->right, result);
      

      }

      // 递归解码(后序遍历) TreeNode* dfsDeserialize(istringstream& data) {

      string val;
      data >> val;
      if(val == "N")        // 递归结束条件:空节点
          return NULL;
      
      // 先序位置
      TreeNode* root = new TreeNode(stoi(val));
      // 递归处理左右子树
      root->left = dfsDeserialize(data);
      root->right = dfsDeserialize(data);
      return root;
      

      } public: // Encodes a tree to a single string. string serialize(TreeNode* root) {

      string result;
      dfsSerialize(root, result);
      return result;
      

      }

      // Decodes your encoded data to tree. TreeNode* deserialize(string data) {

      istringstream istr(data);
      return dfsDeserialize(istr);
      

      } };

// Your Codec object will be instantiated and called as such: // Codec ser, deser; // TreeNode* ans = deser.deserialize(ser.serialize(root));

执行结果:

执行结果:通过

执行用时:40 ms, 在所有 C++ 提交中击败了 78.69% 的用户 内存消耗:30.3 MB, 在所有 C++ 提交中击败了 81.53% 的用户

<a name="svZ16"></a>
## 解法二:中序遍历
中序遍历,将空节点存储为 `'#'`,非空节点存储为 `val + '!'` 的形式(解码时注意可能 `val` 为负数)
```cpp
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
private:
    TreeNode* splitNode(string str, int& idx)
    {
        if(idx >= str.size())
            return nullptr;

        if(str[idx] == '#')
        {
            ++idx;
            return nullptr;
        }
        else
        {
            int val = 0;
            bool neg = false;
            if(str[idx] == '-')
            {
                ++idx;
                neg = true;
            }
            while(str[idx] != '!')
            {
                val = val * 10 + str[idx] - '0';
                ++idx;
            }
            ++idx;
            if(neg)
                val = -val;
            TreeNode* node = new TreeNode(val);
            return node;
        }
    }
public:
    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        string result;
        queue<TreeNode*> nodeQ;
        nodeQ.push(root);
        while(!nodeQ.empty())
        {
            TreeNode* cur = nodeQ.front();
            nodeQ.pop();
            if(cur == nullptr)
                result += "#";
            else
            {
                nodeQ.push(cur->left);
                nodeQ.push(cur->right);
                result += to_string(cur->val);
                result += "!";
            }
        }
        return result;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        int idx = 0;
        TreeNode* root = splitNode(data, idx);
        if(root == nullptr)
            return nullptr;
        queue<TreeNode*> nodeQ;
        nodeQ.push(root);
        while(!nodeQ.empty())
        {
            TreeNode* cur = nodeQ.front();
            nodeQ.pop();
            cur->left = splitNode(data, idx);
            cur->right = splitNode(data, idx);
            if(cur->left != nullptr)
                nodeQ.push(cur->left);
            if(cur->right != nullptr)
                nodeQ.push(cur->right);
        }
        return root;
    }
};

// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));