侧边栏壁纸
博主头像
GabrielxD

列車は必ず次の駅へ。では舞台は?私たちは?

  • 累计撰写 675 篇文章
  • 累计创建 128 个标签
  • 累计收到 22 条评论

目 录CONTENT

文章目录

【队列, DFS, 二叉树】二叉树的序列化与反序列化

GabrielxD
2022-09-06 / 0 评论 / 0 点赞 / 226 阅读 / 883 字
温馨提示:
本文最后更新于 2022-09-11,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

题目

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


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

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

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

示例 1:

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

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

示例 4:

输入:root = [1,2]
输出:[1,2]

提示:

  • 树中结点数在范围 [0, 10^4]
  • -1000 <= Node.val <= 1000

解题

方法一:DFS(前序遍历) 队列

思路

使用递归的方式前序遍历二叉树,并把它序列化为字符串并返回(遇到空节点也需要记录)。例如:

  1
 / \
2   3
   / \
  4   5

应该序列化为:1,2,n,n,3,4,n,n,5,n,n
image-20220906112200969

反序列化的时候把拿到的字符串按照之前规定的分隔符(',')分割放入队列中,然后再次使用前序遍历的顺序构建即可。
image.png

参考:『手画图解』剖析DFS、BFS解法 | 二叉树的序列化与反序列化

代码

public class Codec {
    static final String NULL_NODE = "n";

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        return serializeDfs(root);
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        return deserializeDfs(new LinkedList<>(Arrays.asList(data.split(","))));
    }

    String serializeDfs(TreeNode node) {
        if (node == null) return NULL_NODE;
        return node.val + "," + serializeDfs(node.left) +
            "," + serializeDfs(node.right);
    }

    TreeNode deserializeDfs(Queue<String> queue) {
        if (queue.isEmpty() || NULL_NODE.equals(queue.peek())) {
            queue.poll();
            return null;
        }
        TreeNode node = new TreeNode(Integer.parseInt(queue.poll()));
        node.left = deserializeDfs(queue);
        node.right = deserializeDfs(queue);
        return node;
    }
}
class Codec {
    const string NULL_NODE = "n";

    TreeNode* deserialize_dfs(queue<string>& tree) {
        if (tree.empty() || tree.front() == NULL_NODE) {
            tree.pop();
            return nullptr;
        }
        TreeNode* node = new TreeNode(stoi(tree.front()));
        tree.pop();
        node->left = deserialize_dfs(tree);
        node->right = deserialize_dfs(tree);
        return node;
    }

public:
    // Encodes a tree to a single string.
    string serialize(TreeNode* node) {
        if (!node) return NULL_NODE;
        return to_string(node->val) + "," + serialize(node->left) +
            "," + serialize(node->right);
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        queue<string> que;
        int n = data.length();
        for (int i = 0; i < n; ++i) {
            int j = i + 1;
            while (j < n && data[j] != ',') ++j;
            que.push(data.substr(i, j - i));
            i = j++;
        }
        return deserialize_dfs(que);
    }
};

C++ 可以使用 std::basic_istringstream 简化代码。

参考:【C++】使用istringstream根据分隔符分割字符串

class Codec {
    const string NULL_NODE = "n";

    TreeNode* deserialize_dfs(istringstream& tree) {
        string val;
        getline(tree, val, ',');
        if (val == NULL_NODE) return nullptr;
        TreeNode* node = new TreeNode(stoi(val));
        node->left = deserialize_dfs(tree);
        node->right = deserialize_dfs(tree);
        return node;
    }

public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* node) {
        if (!node) return NULL_NODE;
        return to_string(node->val) + "," + serialize(node->left) +
            "," + serialize(node->right);
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        istringstream iss(data);
        return deserialize_dfs(iss);
    }
};
0

评论区