• 二叉树的序列化与反序列化


    题目来源:https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/ .

    按照 Leetcode 的官方习惯,二叉树的序列化逻辑是根据其「层次遍历」序列来实现的(参考该文章),因此本文以这种方式来解题。

    预备工作

    对于反序列化过程,其输入是一个字符串,我们需要将其转换为 vector<string> ,如 "1,null,2" 需要转换为 {"1", "null", 2"} .

    vector<string> split(string &data, const string &sep)
    {
        size_t l = 0;
        size_t r = data.find(sep, l);
        vector<string> result;
        while (r != string::npos)
        {
            result.emplace_back(data.substr(l, r - l));
            l = r + sep.length();
            r = data.find(sep, l);
        }
        if (l < data.length())
            result.emplace_back(data.substr(l));
        return result;
    }
    

    对于 vector<string> 中的每个元素,构造一个 API,返回对应的二叉树节点(包括空节点):

    TreeNode *generateNode(const string &s)
    {
        return s == NIL ? nullptr : new TreeNode(stoi(s));
    }
    

    其次,需要 2 个常量(以成员变量的形式存在),NIL 是空节点的符号表示,SEPARATOR 是序列化字符串中的分隔符:

    const string NIL = "null";
    const string SEPARATOR = ",";
    

    层次遍历实现

    • 序列化

    与一般的层次遍历几乎一样,唯一不同的地方是:在此处,空节点 nullptr 也进入队列当中

    ❗ 需要注意的是:最后一层均为叶子节点,因此它们的左右孩子均为 null ,按照 Leetcode 的要求,序列化字符串中不包含这些最后一层叶子节点的孩子。

    string levelSerialize(TreeNode *root)
    {
        if (root == nullptr)
            return "";
        queue<TreeNode *> q;
        q.push(root);
        vector<string> result;
        while (!q.empty())
        {
            auto node = q.front();
            q.pop();
            if (node != nullptr)
            {
                result.emplace_back(to_string(node->val));
                q.push(node->left);
                q.push(node->right);
            }
            else
                result.emplace_back(NIL);
        }
        while (result.back() == NIL) result.pop_back();
        string str;
        for (auto &x : result)  str += (x + SEPARATOR);
        if (str.back() == SEPARATOR[0])  str.pop_back();
        return "[" + str + "]";
    }
    
    • 反序列化

    还是是普通的层次遍历算法改过来的~

    TreeNode *levelDeserialize(string &data)
    {
        if (data.empty())  return nullptr;
        if (data.front() == '[' && data.back() == ']')  data = data.substr(1, data.length() - 2);
        auto v = split(data, SEPARATOR);
        int idx = 0, size = v.size();
        auto root = generateNode(v[idx++]);
        assert(root != nullptr);
        queue<TreeNode *> q;
        q.push(root);
        while (!q.empty())
        {
            auto node = q.front();
            q.pop();
            if (idx < size)  node->left = generateNode(v[idx++]);
            if (idx < size)  node->right = generateNode(v[idx++]);
            if (node->left != nullptr)  q.push(node->left);
            if (node->right != nullptr) q.push(node->right);
        }
        return root;
    }
    
  • 相关阅读:
    没有完成的题目
    哈尔滨工程大学 ACM online contest 1008 how many
    POJ 2976 分数规划
    长沙理工 ACM 数位 DP 1488
    POJ 2663
    USETC 1821 AC 自动机
    长沙理工 ACM 分数规划 1494
    正则表达式基础知识(转)
    上传头像代码
    datalist 分页(转)
  • 原文地址:https://www.cnblogs.com/sinkinben/p/13668996.html
Copyright © 2020-2023  润新知