玩命加载中 . . .

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


LeetCode 297. Serialize and Deserialize Binary Tree

LeetCode-297

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.

Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.

Clarification: The input/output format is the same as how LeetCode serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.

Example 1:

Input: root = [1,2,3,null,null,4,5]
Output: [1,2,3,null,null,4,5]

method

  • 序列化

先序遍历,用#来表示空节点,用,作为节点之间的分隔

  1      ->        1
 / \            /     \
2   3          2       3
             /   \   /   \
            #     # #     #

序列化为1,2,#,#,3,#,#,

void dfs(TreeNode *root, string& res) {
    if (!root) {
        res += "#,";
        return;
    }
    res += to_string(root->val) + ",";
    dfs(root->left, res);
    dfs(root->right, res);
    return;
}
string serialize(TreeNode* root) {
    string res = "";
    if (!root) return res;
    dfs(root, res);
    return res;
}
  • 反序列化
  1. 将序列化中的节点值(包括#)提取出来,去掉,,存储在队列中
  2. 也是用先序遍历,每次取队首作为根节点,然后出队,递归处理左右子树

因为要把序列第一个元素删掉,所以用队列比较方便,对队列的修改要用引用,不是回溯,所以同一层会不一样

// Decodes your encoded data to tree.
TreeNode* decode(queue<string>& data) { // 要用引用
    if (data.front() == "#") {
        data.pop();
        return nullptr;
    }
    TreeNode *root = new TreeNode(stoi(data.front()));  // string to int
    data.pop();
    root->left = decode(data);  // 要用引用
    root->right = decode(data); // 不然这两个q是一样的
    return root;
}
TreeNode* deserialize(string data) {
    if (data.size() == 0) return nullptr;
    queue<string> q;
    string s = "";
    for (auto ch : data) {
        if (ch == ',') {
            q.push(s);  // 存储节点值
            s.clear();
        }
        else s.push_back(ch);   // 几个字符合起来才是节点值,比如123
    }
    return decode(q);
}

指针版本的,空节点就只有一个#,没有,

class Solution {
public:
    void dfs(TreeNode *root, string& data) {
        if (!root) {
            data += "#";
            return;
        }
        data += to_string(root->val) + ",";
        dfs(root->left, data);
        dfs(root->right, data);
    }
    char* Serialize(TreeNode *root) {
        if (!root) return "#";
        string s = "";
        dfs(root, s);
        char *res = new char[s.length() + 1];
        strcpy(res, s.c_str()); // s.c_str()返回的是const char*
        return res;
    }
    TreeNode* decode(char *&s) {    // 注意这里是指针的引用
        if (*s == '#') {
            ++s;
            return nullptr;
        }
        int num = 0;
        while (*s != ',') {
            num = num * 10 + (*s - '0');
            ++s;
        }
        ++s;
        TreeNode *root = new TreeNode(num);
        root->left = decode(s);
        root->right = decode(s);
        return root;
    }
    TreeNode* Deserialize(char *str) {
        printf("%s\n", str);
        return decode(str);
    }
};

LeetCode 449. 序列化和反序列化二叉搜索树

序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。

设计一个算法来序列化和反序列化 二叉搜索树 。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。

编码的字符串应尽可能紧凑。

示例 1:

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

method

可以使用『题297』的先序遍历方法,不过这样就没有用到BST的性质了

可以先用先序遍历得到字符串再转为数组,再用先序遍历构造BST

先序遍历构造二叉搜索树:根节点后面比它小的是左子树,比它大的是右子树

void dfs(TreeNode *root, string& res) {
    if (!root) return;
    res += to_string(root->val) + ",";
    dfs(root->left, res);
    dfs(root->right, res);
}

string serialize(TreeNode* root) {
    string res;
    if (!root) return res;
    dfs(root, res);
    return res;
}

TreeNode* decode(vector<int>& nums, int l, int r) {
    if (l >= r) return nullptr;     // [l, r)
    TreeNode *node = new TreeNode(nums[l]);
    int idx = l;
    for (; idx < r; idx++) {
        if (nums[idx] > nums[l]) break; // 找到第一个大于根节点的位置,后面就是右子树
    }
    node->left = decode(nums, l + 1, idx);  // [l+1, idx)
    node->right = decode(nums, idx, r);     // [idx, r)
    return node;
}

TreeNode* deserialize(string data) {
    vector<int> nums;
    int num = 0;
    for (auto c : data) {   // 将以,分割的字符串转为数组
        if (c == ',') {
            nums.push_back(num);
            num = 0;
        }
        else num = num * 10 + c - '0';
    }
    return decode(nums, 0, nums.size());
}

文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录