一. 学习题,一直对这题有些困惑,直接看答案了...
作者:LeetCode
链接:https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/solution/er-cha-shu-de-xu-lie-hua-yu-fan-xu-lie-hua-by-leet/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
方法一:深度优先搜索
1. Binary Tree 的序列化本质上是对其值进行编码,更重要的是对其结构进行编码。可以遍历树来完成上述任务。众所周知,我们有两个一般策略:广度优先搜索(BFS)我们按照高度的顺序从上到下逐级扫描树。更高级别的节点将先于较低级别的节点访问。 深度优先搜索(DFS) 在这个策略中,我们采用深度作为优先顺序,这样我们就可以从一个根开始,一直延伸到某个叶,然后回到根,到达另一个分支。根据根节点、左节点和右节点之间的相对顺序,可以进一步将DFS策略区分为 preorder、inorder 和 postorder 。
2. 然而,在这个任务中,DFS
策略更适合我们的需要,因为相邻节点之间的链接自然地按顺序编码,这对后面的反序列化任务非常有帮助。先序遍历的 DFS 按 root -> left subtree -> right subtree
的顺序递归进行。
3. 我们从根节点 1 开始,序列化字符串是 1,。然后我们跳到根节点 2 的左子树,序列化字符串变成 1,2,。现在从节点 2 开始,我们访问它的左节点 3(1,2,3,none,none,)和右节点 4。(1,2,3,None,None,4,None,None)。None,None, 是用来标记缺少左、右子节点,这就是我们在序列化期间保存树结构的方式。最后,我们回到根节点 1 并访问它的右子树,它恰好是叶节点 5。最后,序列化字符串是按 1,2,3,None,None,4,None,None,5,None,None,.
4. 现在让我们反序列化 1,2,3,None,None,4,None,None,5,None,None, 字符串。它沿着字符串运行,初始化节点值,然后调用自身来构造其左、右子节点。
5. 吐槽一下,代码一直写的不对也是醉了, 究其原因, C++的string好像不能给地址,导致其会跟着递归函数而改变,不具备全局性..
二. 参考其他代码,最好C++版本,看看格式怎么弄得.......
作者:ZZYuting
链接:https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/solution/c-version-by-zzyuting/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1. 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
2. 请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
3. 代码可以好好看看顺便学习C++知识......
4. C++引入了ostringstream、istringstream、stringstream这三个类,要使用他们创建对象就必须包含sstream.h头文件。
istringstream类用于执行C++风格的串流的输入操作。ostringstream类用于执行C风格的串流的输出操作。stringstream类同时可以支持C风格的串流的输入输出操作。
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Codec {
public:
void rserialize(TreeNode* root, stringstream& s) {
//间隔用空格,方便反序列化流的取出操作....
if (root == NULL) s << "NULL ";
else {
s << to_string(root->val) << " ";
rserialize(root->left, s);
rserialize(root->right, s);
}
}
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
//用流进行字符串传输,原因在于字符串没法传地址,会导致递归
//的时候会跟着函数改变,定义stringstream后传入地址,
//相当于全局变量.
stringstream stream;
rserialize(root, stream);
//转换为字符串返回.
return stream.str();
}
TreeNode* rdeserialize(stringstream& data) {
string val;
//反序列化时候,流的输出以空格为间隔.
//只会取出空格间的单词.
data >> val;
if (val == "NULL") {
return NULL;
}
//可以这么做的原因是序列化用的先序遍历,
//则先序遍历第一个是根,然后左右子树递归,
//好好理解一下.
TreeNode* root = new TreeNode(stoi(val));
root->left = rdeserialize(data);
root->right = rdeserialize(data);
return root;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
stringstream stream;
stream << data;
return rdeserialize(stream);
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));