449. 序列化和反序列化二叉搜索树
一、题目
1.题目描述
序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。
设计一个算法来序列化和反序列化 二叉搜索树 。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。
编码的字符串应尽可能紧凑。
示例 1:
输入:root = [2,1,3]
输出:[2,1,3]
示例 2:
输入:root = []
输出:[]
提示:
- 树中节点数范围是
[0, 10^4]
0 <= Node.val <= 10^4
- 题目数据 保证 输入的树是一棵二叉搜索树。
2.基础框架
C++基础框架代码如下:
string serialize(TreeNode* root){
}
TreeNode* deserialize(string data){
}
3.解题思路
- 题目分析
serialize()
函数的实现思路:
- 算法采用BFS,即按层序遍历的顺序访问二叉树的结点,并将结点的值由int类型转换为string类型保存到字符串
res
中,以" "
为分隔符。 - 如果当前访问到的是空结点,则以
#
表示并将#
存储到字符串res
中,注意#
后面要追加
分隔符" "
。 - 直到队列
q
为空时,说明二叉树遍历完所有结点,最终得到了序列化字符串res
。
deserialize()
函数的实现思路:
- 该函数实现反序列化,也就是将按同一规则的序列化字符串还原成二叉搜索树,所谓的同一规则,也就是在上面
serialize()
函数中制定的,以" "
为分隔符,#
表示空结点,并且按层序遍历访问的规则。所以在同一规则的基础上,可以对二叉搜索树进行还原。 - 将序列化字符串
res
中提取出每个访问到的结点所需要的值,这里是通过strtok()
函数进行提取,只要以" "
为分割符,就会得到原来结点的值,不过还需要将它从字符串转变为整型,所以需要使用atoi()
函数。 - 提取的值有两种情况,要么是表示空结点的
#
,要么是字符类型的数字,如果是#
则跳过处理。 - 如果当前token值不为
#
,表示该结点不为空结点,那么就将其左、右结点分别添加到队列中。 - 当
token
为空时,即成功还原二叉搜索树。
-
实现代码:
/** * 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 { public: // Encodes a tree to a single string. string serialize(TreeNode* root) { if (root == nullptr) return ""; string res; queue<TreeNode*> q; q.push(root); while (!q.empty()) { TreeNode* node = q.front(); q.pop(); if (node) res.append(to_string(node->val) + " "); else res.append("# "); if (node) { q.push(node->left); q.push(node->right); } } return res; } // Decodes your encoded data to tree. TreeNode* deserialize(string data) { TreeNode* node = nullptr; TreeNode** dummy = &node; queue<TreeNode**> q; q.push(&node); char* token = strtok(const_cast<char*>(data.c_str()), " "); while (token) { int n = q.size(); for (int j = 0; j < n; ++j) { TreeNode** node = q.front(); q.pop(); if (strcmp(token, "#") != 0) { *node = new TreeNode(atoi(token)); q.push(&((*node)->left)); q.push(&((*node)->right)); } token = strtok(nullptr, " "); if (token == nullptr) break; } } return *dummy; } }; // Your Codec object will be instantiated and called as such: // Codec* ser = new Codec(); // Codec* deser = new Codec(); // string tree = ser->serialize(root); // TreeNode* ans = deser->deserialize(tree); // return ans;
4.知识点
- 二叉树的层次遍历
- 二叉树的创建
- 队列
- 字符串使用
strtok()
可指定分隔符进行截取。 itoa()
:将整型转换成字符串to_string()
:将字符串转变成整型